Introduction-to-React-JS

本文深入探讨了ReactJS这一革命性框架,它挑战传统约定,采用函数式编程,提供组件为中心的方法,实现虚拟DOM优化渲染,提高Web应用性能。通过基础功能介绍、JSX使用、组件创建、操作处理、测试实践、Flux架构应用,以及如何通过Reflux简化数据流,展示了React如何革新Web开发体验。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

                                       [转载 fakefisk]

ReactJS介绍

引子

当你第一次看到 React 的时候,一定是十分怀疑的,特别是把 HTML 揉进代码里违背了传统的那些约定,看起来真的像是一个 “坏注意”。

但是这就是 React及其类似的框架,他们挑战了那些约定规则,然后用这种更易接受的方式代替这些约定。
作为一个开发者,有时候改变思考方式是你向前走的一个必经之路。这就是 React 对我的影响,它建立在函数式编程上带给了我很多有意思的想法。

基础功能

在你能理解 React 是如何改变 Web 开发之前,这里有一些东西你需要知道的。React 它本身并不能完成所有的事情,它只能解决一些视图上的问题,你仍然需要一些东西去帮助它完成事情。
最伟大的和最差劲的框架总是企图给你建立一个笼子,当你在他们划定的地盘里能够完成它们期望处理的任何需求,一切都是很好的。但是,当你到达边界的时候,就会开始有问题了。
在一个库驱动开发方法内,你是不被限制的,最初你可能是高效地完成需求,但是伴随时间的推进,问题开始变得严峻起来,你需要更多可行的选择。

JSX 的基础

React 为前端开发提供了一个组件为中心的方法,你可以为你的应用设计一个更小的组件,所有组件有各自的目的。甚至极端来说,一个组件可能包含它自身的逻辑,结构和基本的样式。这里有个 JSX 的例子:

...
<TodoItem className='urgent' owner={owner} task='Make a dinner' />
...

你可以看到一个基本功能的 JSX,这里使用的是javascript,我们使用className 替代了class。此外,我们定义了一些自定义属性 owner 和 task,owner 的值是从 JSX 环境中一个变量 owner 注入,而我们为 task 提供了一个固定的值。

在实践中,你可以会更喜欢根据你的数据模型结构来稍微调整其结构,虽然是 React 进阶的知识点了。

我们可以用那些 {} 来混合普通 JavaScript 代码,我们可以用这个点像这样去去渲染一个 TodoItem 列表(ES 语法):

<ul>
{todoItems.map( (todoItem, i) =>
    <li key={'todoitem' + i}><TodoItem owner={todoItem.owner} task={todoItem.task} /></li>
)}
</ul>

你可能注意到这里有些特殊的地方。什么是 key 属性?这是告诉 React 这个项的准确顺序。如果你不像这样提供列表项的唯一 Key 的话,React 会警告你:它没办法保证是正确的顺序。

React 实际上要做的是在真实 DOM 上实现了虚拟 DOM(简称 VDOM)。 这是一个 DOM 的子集, React 能够优化它的渲染。这种优化方法的主要优势是它让 React 能够避开困恼我们多年的 DOM 性能损耗。这就是 React 高性能的原因。

整体组件

为了让你更加清楚了解组件是什么样子,让我们拓展 TodoItem 例子来感受一下(ES6 + JSX),我已经搞完了,然后我们来过一遍代码看看:

var React = require('react');


module.exports = React.createClass({
    getInitialState() {
        return {
            // 让我们保持追踪看看我们给项点了多少次赞
            likes: 0,
        };
    },
    render() {
        var owner = this.props.owner;
        var task = this.props.task;
        var likes = this.state.likes;

        return <div className='TodoItem'>
            <span className='TodoItem-owner'>{owner}</span>
            <span className='TodoItem-task'>{task}</span>
            <span className='TodoItem-likes'>{likes}</span>
            <span className='TodoItem-like' onClick={this.like}>Like</span>
        </div>;
    },
    like() {
        this.setState({
            likes: this.state.likes + 1
        });
    },
});

在上面你可以看到一些基础的 React 组件的特征。一开始我们创建了一个组件的类–通过React.createClass函数,然后我们在初始化的时候定义一些状态,接着我们定义渲染方法render,最后我们为我们的处理器handler,如果它们存在的话,定制了一些回调。在这个例子中,我决定去实施一个额外的功能,liking方法(点赞)。当前的这个实现只是保持了一个跟踪点赞组件的计数。

在实践中,你需要把点赞计数传输给后端,然后添加一些验证,不过目前这个阶段对于理解 State 在 React 中的是如何使用的已经是一个非常好的开端了。

稍作说明:在react 组件component官方文档中, getInitialStaterender 是 React 组件的生命周期一部分。组件component也有额外的能够让你去设置加载 jQuery 插件之类的适配器的钩子。

在例子中的 CSS 的命名是根据 Suit CSS 约定处理后的,这样对我来说看起来非常清楚,这只是一种解决方案而已。

处理操作

现在让我们开始修改我们的 TodoItems 的 owner。为了简化这个目的,我们假设 owner 只是一个字符串而且只有一个。基于这个设计,在用户界面里增加一个输入框给用户来修改用户名,修改后是这样的:

var React = require('react');
var TodoItem = require('./TodoItem.jsx');

module.exports = React.createClass({
    getInitialState() {
        return {
            todoItems: [
                {
                    task: 'Learn React',
                },
                {
                    task: 'Learn Webpack',
                },
                {
                    task: 'Conquer World',
                }
            ],
            owner: 'John Doe',
        };
    },

    render() {
        var todoItems = this.state.todoItems;
        var owner = this.state.owner;

        return <div>
            <div className='ChangeOwner'>
                <input type='text' defaultValue={owner} onChange={this.updateOwner} />
            </div>

            <div className='TodoItems'>
                <ul>{todoItems.map((todoItem, i) =>
                    <li key={'todoitem' + i}>
                        <TodoItem owner={owner} task={todoItem.task} />
                    </li>
                )}</ul>
            </div>
        </div>;
    },

    updateOwner() {
        this.setState({
            owner: e.target.value,
        });
    },
});

在render方法中,我们定义了一个Div和其中的输入框。

当然我们可以把 TodoItems 和 ChangeOwner 分离出去,但是我暂时不这么做了。React 默认提供了单向数据绑定,关于某些其他的设置,这里有很多的说法。 React 提供了 ReactLink 帮助器helper来帮助我们处理这个特殊案例。

尽管双向数据绑定的缺失–如angularJS和backbone等–听起来让人沮丧,但实际上并不是一件坏事,它能够让系统更加轻松的运行。你必须简单地跟踪流。这也是Flux 架构中的精彩部分。认识它的最简单的方式是去想一个无限瀑布流,或者贪吃蛇。这就是 在React 的世界里,通常工作的流程。对比一下,双向绑定方式让人感觉更加杂乱混乱。

使用一个Mixin

如果我们想使用 ReactLink helper来帮助我们包装DOM的话,就像下面这样使用:

// ReactLink 是一个插件,所以我们需要把它引入。
var React = require('react/addons');

...

module.exports = React.createClass({
    mixins: [React.addons.LinkedStateMixin],

    ...

    render() {
        var todoItems = this.state.todoItems;

        return <div>
            <div className='ChangeOwner'>
                <input type='text' valueLink={this.linkState('owner')} />
            </div>

            <div className='TodoItems'>
                <ul>{todoItems.map( (todoItem, i) =>
                    <li key={'todoitem' + i}>
                        <TodoItem owner={owner} task={todoItem.task} />
                    </li>
                )}</ul>
            </div>
        </div>;
    },
});

现在我们可以跳过绑定 onChange 事件了,React.addons.LinkedStateMixin 封装了逻辑。Mixins 给我们提供了一种封装可以共享关注点,并能简单重用的方法。


现在拓展例子已经非常容易了,你现在应该就可以拓展 Todo 列表,或者把抽取不同的部分分离到各种组件,这完全取决于你如何来开发。这里只是对此话题的一个简单介绍。

测试

如果你对这个 Todo 应用是很认真的,那么我推荐 Jest,使用它来进行测试。刚开始让测试运行起来可能有一点挑战,但是在你学习了解了它的一些基础的 API 之后,就会变得简单了。最基本的是你要实例化一个带有一些属性的组件,然后用 Jest 查询 DOM,最后断言DOM中的值恰如你期望的值。

当你站在组件层级之上时,就有了比如类似 Selenium 的工具,你可以在更高层级使用标准的端对端测试工具。

Flux 架构及其变种

就想你在上面看到的,把一些组件放到一起就可以开始创建一个应用,你可以用 props 和 state 做的更多,或者在 getInitialState 中使用 AJAX 加载数据然后传给其他组件。这些使用一段时间之后可能会觉得有些笨拙。为什么?比如,我们的组件们需要知道如何和后端通讯。

所以出现了 Flux 架构和它的一些演化变种,我会介绍 Reflux ,一种简化的 Flux 变种。在你理解这个简化的版本后,还可以浏览这个 understanding Flux 来完整详尽全面了解 Flux。

并且,为了查看刚才我们讨论的试图组件,Reflux 引入了 Actions 和 Stores 的概念。
现在,整个数据流是这样的:组件 -> Actions -> Stores -> 组件。这样你可以在一个组件中控制触发一些 Action 然后执行一些操作(比如 PUT)然后更新 Store 的状态。而状态的更新再被传播给监听 Store 的那些组件们。

在我们的这个 Todo 例子中,我们定义了基本的 TodoActions, 比如创建、更新、删除之类的。我们也有个 TodoStore,它是整个 TodoList 的数据结构中心,组件们会读取那里的数据,然后适当得展现出来。

使用Reflux 的开发,旧不在这里详细讲述了,我只是想说明如何处理从纯 React 扩大的一种可能的方式。你需要去探索各种选择,然后深入理解那些架构。那些想法都差不多,就是细节不太一样,都有各自的一些缺点有待考略。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值