最新版React入门
工欲善其事必先利其器,因为react崇尚的是,react一体化. 即,使用js拯救世界. 所以,我们需要先将支持react的webpack 工具解决. webpack 配置这里主要使用的是这些模块: "babel-loader": "^6.2.4","babel-core": "^6.8.0","babel-loader": "^6.2.4","babel-plugin-transform-es2015-arrow-functions": "^6.8.0","babel-preset-es2015": "^6.6.0","react-dom": "^15.2.1","react" : "^15.2.1" 将这些文件放到package.json中,然后使用npm install 即可. var path = require('path'),node_modules = path.resolve(__dirname,'node_modules'); module.exports = { // context: __dirname + "/app/src/entry",entry: { app:"./dev/app" },//演示单入口文件 output: { path: path.join(__dirname,'/dev/dist'),//打包输出的路径 filename: '[name].entry.js',//打包后的名字 },module: { loaders: [{ test: /.js|.jsx$/,exclude: /(node_modules|bower_components)/,loader: 'babel?presets[]=es2015' //加载使用loader } ] },plugins: [ ],watch: true }; 这里需要注意一下,由于版本的问题,webpack 在v1.13之后,会默认给entry文件添加extensions. 所以如果你的entry写成了, webpack --display-error-details 来进行排查. ok,现在我们正式进入react时间 react 入门初期,react基本的操作无外乎就是围绕着,Component和ReactDOM进行编写和渲染。 以前,react并没有分的太细化,不过在version 0.14版本后,ReactDOM和Component就分开了,主要还是因为React Native的缘由.
上面,我们已经下载好了 import React,{Component} from 'react'; import ReactDOM from 'react-dom'; class Hello extends Component{ render(){ return ( <h1>Hello world</h1> ); } } ReactDOM.render(<Hello />,document.getElementById('container')); 重要的是Hello 类中的render方法. 通过return,返回虚拟的DOM,然后经过ReactDOM将虚拟的DOM,渲染到指定节点内部. 动态内容假如我们现在想要在render中,使用变量,so how to do? class Hello extends Component{ render(){ let name="jimmy"; return ( <h1>Hello {name}</h1> ); } } 嵌套UIReact之所以这么流行,就是因为他的可复用性. 通过 class UI_item extends Component{ render(){ return ( <UL></UL> ); } } class UL extends Component{ render(){ return ( <ul> <Li_item name="jimmy">ok</Li_item> <Li_item name="sam">yes</Li_item> </ul> ) } } class Li_item extends Component{ render(){ return ( <li>my name is {this.props.name} and my content is {this.props.children}</li> ) } } 在进行组件复用时,重用UI 和写HTML一样,使用闭合标签,添加属性等等. 不过,这里需要注意一下,在JSX语法中,class属性需要换成 className(因为内部冲突).
this.props 在组件复用中,是占很重要的地位的,可以说,他是parent和children 组件通信的重要通道,父组件 赋值,子组件处理. like:
通常来说,写一个整体的UI 有两种方式,一种是Top-Down,一种是Bottom-Up. 两者都行,只是思考的方式不一样,不过一般TD(自顶向下)方式比较普遍些. 如果你想利用循环生成jsx的话,可以使用: class UL extends Component{ render(){ let tasks = []; for(var i=1,len=this.props.number;i<=len;i++){ tasks.push( <Li_item key={i} number={i}>list</Li_item> ) } return ( <ul> {tasks} </ul> ); } } 但需要注意的是,你不能直接写为: return ( {tasks} ) 如果这样写的话,react是不会让你通过的. 因为他认为你这个是不合法数据,一般来说,不能在第一层里面直接写入: 状态改变react 提供另外一个状态属性-
这里,我们通过简单的改变,父组件的state,来实现节点的重流和重绘. class UI_item extends Component{ constructor(){ super(); this.state={ origin:true } } render(){ let number = 5; if(!this.state.origin){ number*=2; } return ( <div> <button onClick={()=>{this.doubleNumber()}}></button> <UL number={number}></UL> </div> ); } doubleNumber(){ this.setState({ origin:!this.state.origin }); } } 上面的代码其实有点绕的. 这里补充几点,相信看过之后,再回去看代码也就明白了.
另外,你新增this.props也是会重新渲染节点的. 结合,上面的this.props 可以大概了解,React 提供的精华架构.
事件绑定解析React 之所以高性能,不仅在于虚拟DOM的算法,事件绑定也在一定程度提升性能. 因为React的所有事件都是绑定在document 根元素上. render(){ let number = 5; if(!this.state.origin){ number*=2; } return ( <div> <button onClick={this.doubleNumber.bind(this)}}></button> <UL number={number}></UL> </div> ); } 来看一下,React 提供的事件.
小心JSX的坑React 在提出本身的同时,也提出了JSX语法. 这是为什么呢? // JSX <h1>Hello World</h1> // React 方法调用 React.createElement("h1",null,"Hello World"); 当你写出JSX 的时候,React在背后已经帮你解析成对应的方法了. 所以,这样隐形的API,为什么不用呢? 驼峰命名的属性在JSX中,给tag添加属性时,需要使用驼峰命令. 即. // HTML <input type="text" name="usrname" maxlength="10"> // JSX <input type="text" name="usrname" maxLength="10"><br> 但像,这样的 标签闭合很简单,就是所有标签必须闭合. 比如像 <img src="..." /> only one node这里,应该是很多初入React 童鞋常常犯的~ 可能对函数的了解还未透彻. 比如一个函数: function add(){ return (1,2); } add(); 上面的结果是多少? // 正确 return( <h1>Hello World</h1> ) // go die return ( <h1>Hello World</h1> <h2>Have a nice day</h2> ) 改写一下,你只能返回一个节点: return ( <p> <h1>Hello World</h1> <h2>Have a nice day</h2> </p> ) don't use if-else在JSX,一般不要乱用if-else. 因为if-else 是不会返回任何值的。 // 报错 return ( <li data-set={if(true){"ok"}}>jimmy</li> ) 推荐情况是,使用三元运算(ternary). 因为他可以返回值. return ( <li data-set={true?'ok':0}>jimmy</li> ) 置于为什么,我们可以在这里剖析一下JSX语法的结构. 前文已经提到了,JSX其实就是React.createElement(). 我们的属性其实,就是当做createElment参数的 // JSX <div className={if (condition) { "salutation" }}>Hello JSX</div> // 翻译 React.createElement("div",{className: if (condition) { "salutation"}},"Hello JSX"); 这里,有点基本常识的应该知道,对象里面怎么执行... 除非你有返回值. 空格省略React在渲染的时候,会默认忽略掉元素间的空格. 估计是考虑到了 <li >{this.props.children}_{this.props.number} <a href="">ok</a> <a href="">yes</a> </li> 这样渲染的结果是
不过,如果你仅仅是填写文本的话,里面的空格就不会被忽略。如果,你想在元素之间添加上空格的话. 可以这样写: <li > <a href="">ok</a> {" "} <a href="">yes</a> </li> JSX的评论在JSX中,写评论的话,需要注意他的注释方式: /* comment */ 另外,如果你的注释是childElement,则需要使用 <Nav> {/* this is a child comment */} <Person /* multi line comment */ name="sam" // end of line comment /> </Nav> 上面的demo 基本上把所有注释情况都包含了. 动态插入HTML以前,我们纯原始写组件的时候,常常利用的就是element的innerHTML属性. 即,直接在html tag里面添加string,然后利用内部渲染,将element渲染出来. <li> {this.dynamicP()} </li> // 动态脚本 dynamicP(){ let p = "<p>123</p>"; return p; } 但是,这样容易犯的一个错误就是XSS,因为XSS最常用的手段就是动态恶意脚本的插入. 有兴趣的童鞋,可以参考一下我的xss之网页安全.
当有时候,我们又不得不使用动态的String当做HTML插入,那应该怎么做呢? <span dangerouslySetInnerHTML={{__html:dynamicP()}} /> 这样,React就会对插入的HTML解除XSS的限制. 表单输入为什么说表单输入在React里面也是一块需要注意的呢? <input type="search" value="React" /> so how to solve it? class Search extends Component { constructor(){ super(); this.state={ value:"React" } } render() { return ( <div> Search Term: <input type="search" value={this.state.value} onChange={this.handleChange.bind(this)} /> </div> ) } handleChange(event){ this.setState({ value:event.target.value }) } } 通过输入,触发onChange,然后onChange 触发this.setState,重新渲染DOM。get~ 线上demo 另外,表单输入,还需要注意另外两个ele. textarea和select. textArea 在React中,textarea的书写格式和HTML中有些不同 // HTML <textarea>This is the description.</textarea> // React <textarea value="This is a description." /> 该element 也需要绑定onChange时间才行. select 元素的写法和原始HTML差别不大,只是里面的选取默认的option需要改变一下。 在HTML中,书写默认的option 只需要添加selected属性即可. 但在React,则需要手动指定value才行. <select value="B"> <option value="A">A</option> <option value="B">B</option> <option value="C">C</option> </select> 反模式表单这里所谓的anti-pattern(反模式) 听起来逼格挺高的. in fact,他还是表单. 只是你不用写value属性. 而这里的反模式实际体现在,你不用绑定onChange事件,元素中的内容,也能随着用户的输入自动变化. render() { return ( <form> {/* controled component */} <input type="text" value="fixed" /><br/> {/* uncontroled component */} <input type="text" /> </form> ); 线上demo请参考: JSfiddle 我们总结一下:
内部属性trickkey的使用React 以他Virtual DOM 而闻名遐迩,通过造出一个Virtual DOM,然后,通过一种比较算法,得出最新的DOM结构,从而让页面性能损耗降到最低. 现在我们考虑一种情况. return ( <ul> <li></li> <li></li> <li></li> <li></li> <li></li> <li></li> </ul> ); 当其中的几个节点需要变为: <ul> <li></li> <li></li> <li>1</li> <li></li> <li>2</li> <li></li> </ul> React会怎么做... 他首先会提示你,孩纸,你这样不行... 因为,这样的实现方法是在是太多了. CRUD 哪一种都可以实现上述行为. 所以,React需要你手动的设置一个key值,来帮助他标识,你改动的list是哪一个~ render() { let lis = []; for(var i=0;i<4;i++){ lis.push(( <li key={i} >{i}</li> )) } return ( <ul> {lis} </ul> ); } 谨慎的refsrefs 实际上是一种,黑魔法,又可以称为语法糖. 因为他不需要我们手动的使用document.getElementxxx 来获取节点. 他已经帮你把dirty work 给干好了. 我们只需要使用this.refs.xx 来获取指定节点即可. 但是,官方是不提倡这种做法的,因为这样破坏了数据的流向性. React本来是用过render,来改变元素的状态,但是,如果从外面使用this.refs 改变 DOM的话,有可能会造成virtual DOM和actual DOM不统一的情况. constructor(){ super(); this.number = 0; } render() { return( <div> <button onClick={this.clickButton.bind(this)}>click me</button> <span ref="text">I will be changed</span> </div> ) } clickButton(){ let text = this.refs.text; text.innerHTML = this.number++; } 注意一下,属性书写是用 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |