We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
reactjs是来自facebook公司的用于构建用户界面的JavaScript库。
reactjs
facebook
GitHub地址:https://github.com/facebook/react
reactjs的两个衍生项目也值得注意。
react-native
react-canvas
reactjs的jsx语法,让许多人感觉仿佛回到了原始社会。这么多年努力地让html\css\javascript三者分离,好不容易走到今天,reactjs却走回老路,让人难以接受。我也几次三番因为jsx而放弃了解reactjs。
jsx
目前体验下来,发觉那是误解。
reactjs比其他前端模板引擎更彻底的分离html与javascript。前端模板引擎,绝大多数基于html字符串;而reactjs不是。能接受前端模板引擎的人,也能接受jsx。
jsx的实质是:用xml的语法写函数调用。它没有拼接html字符串,也不要求一定要使用jsx,手写函数调用,也是可以的。
xml
在原生DOM中,用js构造dom的方式是这样的:
DOM
js
dom
//要构造的dom:<a class="link" href="https://github.com/facebook/react">React<a> var a = document.createElement('a') a.setAttribute('class', 'link') a.setAttribute('href', 'https://github.com/facebook/react') a.appendChild(document.createTextNode('React'))
如你所见,它颇为繁琐,我们可以封装一下:
//第一个参数为node名 //第二个参数为一个对象,dom属性与事件都以键值对的形式书写 //第三个到第n个为子node,它们将按参数顺序出现, //在这个例子中只有一个子元素,而且也是文本元素,所以可以直接书写,否则还得React.createElement一下 var a = React.createElement('a', { className: 'link', href: 'https://github.com/facebook/react' }, 'React')
如上,从html语法到js构造dom,再到React.createElement的封装。
html
React.createElement
现在有个编译工具,可以让你用html语法来写React.createElement,部署上线前编译回来。你愿意吗?
html语法
不管你的答案是什么,但这就是jsx的一半真相。
正是由于jsx不是html字符串,所以有如下特点:
class
for
className
htmlFor
checked
//在其他前端模板引擎中,可以这么做,因为是拼接字符串 var checkbox = <input type="checkbox" {this.props.selected ? 'checked' : ''} /> //但在jsx中,这是错误的,因为无法构成键值对,要有个key=value的格式,所以得这样 var checkbox = <input className="class是js的保留字" type="checkbox" checked={this.props.selected} /> //编译后: var checkbox = React.createElement('input', { type: 'checkbox', className: 'class是js的保留字', checked: this.props.selected })
//这样写是错误的 var MyComponent = React.createClass({ render: function() { return <div>first div</div><div>second div</div> } }) //因为编译后,return 两个函数调用,就算不报错,也只调用第一个函数,不合意图 var MyComponent = React.createClass({ render: function() { return React.createElement('div', null, 'first div') React.createElement('div', null, 'second div') } }) //所以有时难免要增加dom层级 var MyComponent = React.createClass({ render: function() { return ( <div> <div>first div</div> <div>second div</div> </div> ) } }) //编译后,合乎语法和编程意图了 var MyComponent = React.createClass({ render: function() { return React.createElement('div', null, React.createElement('div', null, 'first div'), React.createElement('div', null, 'second div')) } })
html5
//不合规则 <tap /> //合乎规则 <Tap />
web component是下一代的前端标准,提供了shadow dom、templete元素、Imports与自定义元素的功能。其中自定义元素提供了生命周期回调函数:
web component
shadow dom
templete
Imports
自定义元素
createdCallback
attachedCallback
detachedCallback
attributeChangedCallback
在reactjs中也有相似但更丰富的生命周期方法:
componentWillMount
componentDidMount
componentWillReceiveProps
shouldComponentUpdate
true/false
componentWillUpdate
componentDidUpdate
componentWillUnmount
reactjs与web component的关系,在我个人看来:reactjs是纯js实现的一种component标准,它可以与DOM无关,甚至与Web无关。
component
在reactjs中注册组件像这样:
//reactjs跟objective-c在方法命名上有些相似,使劲儿用全称,与传统js编程的缩写习惯相悖 var MyComponent = React.createClass({ //每个组件必须有render方法 render: function() { return <div className={this.props.className}> //jsx遇大括号就当作js表达式来看待 //map返回的数组会自动展开 { this.props.textList.map(function(text) { return <p>text</p> }) } </div> } }) //像这样使用 var TestComponent = React.createClass({ render: function() { return ( <div> <MyComponent className="组件内部的this.props.className来自它被调用时传递的参数,就是我啦" textList={['组件的this.props.textList', '就是我啦', '用花括号包裹', '以便让jsx将我作为数组直接量的表达式来看待']} /> </div> ) } }) //这里才是插入dom,用React.render方法 //第一个参数为React组件,第二个参数为DOM React.render( <TestComponent />, document.body )
总的来说,reactjs允许我们用React.createClass来拓展React.createElement的参数范畴。
React.createClass
之前说了jsx的一半真相,另一半是,React.createElement并没有直接了当的用js构造dom,它构造了一种数据结构。
使用reactjs时,表面上我们在操作dom,其实是操作数据,reactjs通过自己的dom diff算法,对比前后的数据,找到diff差异点,按最小粒度更新视图。
dom diff
diff
正因如此,reactjs的UI层才是可替换的,构造另一套从数据到视图的映射逻辑,就能应用在canvas乃至手机原生UI上。
UI
从数据到视图
canvas
reactjs组件内部的this.props对象,是组件实例的父级组件提供的,提供方式就像写html属性一样。
this.props
组件实例
如此,父级复父级,数据可以从最顶层的组件实例,层层传递到最底层的组件中去,然而反过来却不行,这就是单向数据流的意思。
//最底层的todo var Todo = React.createClass({ render: function() { return ( //只有html属性和data-*以及aria-*才会显示在dom中,其余的key或其他,是扩展性质的,便于向下级组件传递数据 <li title={this.props.time} key={this.props.id}> <input type="checkbox" checked={this.props.completed} /> <label>{this.props.title}</label> </li> ) } }) //todo的父级组件 var TodoList = React.createClass({ render: function() { return ({ <ul>{ this.props.todos.map(function(todo) { //形如ES6的属性展开式语法,等价于用key=value的形式一个个书写 return <Todo {...todo} /> }) }</ul> }) } }) //todoList的父级组件 var TodoApp = React.createClass({ render: function() { return ( <TodoList todos={this.props.todos} /> ) } }) //模拟的todos数据 var data = [{ id: new Date().getTime(), time: new Date().toLocaleString(), title: '第一个待办事项', completed: false }, { id: new Date().getTime(), time: new Date().toLocaleString(), title: '第二个待办事项', completed: true }] //渲染TodoApp组件到#todo-app,数据从TodoApp传递到TodoList,从TodoList传递到Todo,在Todo中展开为一种DOM结构并注入数据,展示在前端页面中 React.render( <TodoApp todos={data} />, document.getElementById('todo-app') )
reactjs是有趣且富有生命力与表现力的javascript库,有其适用的场景,也有许多需要注意的事项与容易踩到的坑。
javascript
总体而言,学会它不会让人后悔(想想那些学angular1的同学吧)。
附上我用react+requirejs实现的todomvc,编码过程的不愉快主要在:jsx to js, modules to build,编译和打包的繁琐。
react
requirejs
todomvc
链接地址:
The text was updated successfully, but these errors were encountered:
No branches or pull requests
reactjs学习体验
reactjs 是什么?
reactjs
是来自facebook
公司的用于构建用户界面的JavaScript库。GitHub地址:https://github.com/facebook/react
reactjs的两个衍生项目也值得注意。
react-native
:用reactjs写手机appreact-canvas
:用canvas代替臃肿缓慢的DOM作为UI,在移动端获得能与原生应用媲美的流畅效果reactjs 真的将html/xml和js代码混杂在一起吗?
reactjs的
jsx
语法,让许多人感觉仿佛回到了原始社会。这么多年努力地让html\css\javascript三者分离,好不容易走到今天,reactjs却走回老路,让人难以接受。我也几次三番因为jsx
而放弃了解reactjs。目前体验下来,发觉那是误解。
reactjs
比其他前端模板引擎更彻底的分离html与javascript。前端模板引擎,绝大多数基于html字符串;而reactjs
不是。能接受前端模板引擎的人,也能接受jsx
。jsx
的实质是:用xml
的语法写函数调用。它没有拼接html字符串,也不要求一定要使用jsx
,手写函数调用,也是可以的。在原生
DOM
中,用js
构造dom
的方式是这样的:如你所见,它颇为繁琐,我们可以封装一下:
如上,从
html
语法到js
构造dom
,再到React.createElement
的封装。现在有个编译工具,可以让你用
html语法
来写React.createElement
,部署上线前编译回来。你愿意吗?不管你的答案是什么,但这就是
jsx
的一半真相。正是由于
jsx
不是html字符串,所以有如下特点:html
的class
与for
属性在js
里是保留字,所以jsx
里要用别名className
与htmlFor
html
的checked
属性jsx
要求标签一定要闭合,html5
中不强制要求闭合的,在jsx
也都要闭合,以便识别html
标签区分。reactjs与web component
web component
是下一代的前端标准,提供了shadow dom
、templete
元素、Imports
与自定义元素
的功能。其中自定义元素
提供了生命周期回调函数:createdCallback
: 创建时调用attachedCallback
: 添加到dom树时调用detachedCallback
: 从dom树衣橱时调用attributeChangedCallback
:属性改变时调用在
reactjs
中也有相似但更丰富的生命周期方法:componentWillMount
: 初始化渲染前调用componentDidMount
: 初始化渲染后调用componentWillReceiveProps
: 接受新props时调用shouldComponentUpdate
:接受新props或state时调用,返回值true/false
决定是否更新视图componentWillUpdate
: 在接收到新的 props 或者 state 之前立刻调用。在初始化渲染的时候该方法不会被调用componentDidUpdate
:在组件的更新已经同步到 DOM 中之后立刻被调用componentWillUnmount
: 在组件从 DOM 中移除的时候立刻被调用reactjs
与web component
的关系,在我个人看来:reactjs
是纯js
实现的一种component
标准,它可以与DOM无关,甚至与Web无关。在
reactjs
中注册组件像这样:总的来说,
reactjs
允许我们用React.createClass
来拓展React.createElement
的参数范畴。React.createClass
方法,可以提供新的html标签给React.createElement
,创造了封装复杂dom结构、组件化的空间reactjs 的虚拟dom
之前说了
jsx
的一半真相,另一半是,React.createElement
并没有直接了当的用js构造dom,它构造了一种数据结构。使用
reactjs
时,表面上我们在操作dom,其实是操作数据,reactjs
通过自己的dom diff
算法,对比前后的数据,找到diff
差异点,按最小粒度更新视图。正因如此,
reactjs
的UI
层才是可替换的,构造另一套从数据到视图
的映射逻辑,就能应用在canvas
乃至手机原生UI
上。reactjs 的单向数据流
reactjs
组件内部的this.props
对象,是组件实例
的父级组件提供的,提供方式就像写html属性一样。如此,父级复父级,数据可以从最顶层的组件实例,层层传递到最底层的组件中去,然而反过来却不行,这就是单向数据流的意思。
结语
reactjs
是有趣且富有生命力与表现力的javascript
库,有其适用的场景,也有许多需要注意的事项与容易踩到的坑。总体而言,学会它不会让人后悔(想想那些学angular1的同学吧)。
附上我用
react
+requirejs
实现的todomvc
,编码过程的不愉快主要在:jsx to js, modules to build,编译和打包的繁琐。链接地址:
The text was updated successfully, but these errors were encountered: