React个人学习笔记
元素渲染
通过 ReactDOM.render()
方法渲染页面, 可以使用 ES6 class 来定义一个组件:
如何解析HTMl里面的空格:
1. 使用空格的 unicod 编码 : \u0020
2. 使用 dangerouslySetInnerHTML, 不建议使用,容易受到XSS攻击
class Welcome extends React.Component { render() { var htmltest = "Hellow World" {/* 注释 */} return ( <h1>Hello, {this.props.name}</h1> <p>Hellow\u0020World</p> <div dangerouslySetInnerHTML={{__html: htmltest}}></div> ) } }
组件的嵌套
import LessonsLeft from './LessonsLeft/index' class Welcome extends React.Component { render() { return (<div> <LessonsLeft /> <h1>Hello, {this.props.name}</h1> </div>) } }
组件的数据状态state
声明当前组件的变量,必须通过 this.setState() 改变变量值,或者通过 this.forceUpdate() 手动触发DOM更新
var testAPP = React.createClass({ getInitialState:function(){ // 使用 getInitialState 声明state变量 return { testData: '声明变量' } }, handleClick: function() { // 通过 this.setState() 改变变量的值, this.setState({ testData: '更改了变量值' }) // 通过 this.forceUpdate() 改变变量的值, // this.state.testData = '更改了变量值' // this.forceUpdate() }, render: function() { return ( <div> <button onClick={this.handleClick}>点击更改变量</button> {this.state.testData} </div> ) } }) React.render( </testAPP>, document.getElementById('app') )
在使用类的写法中,state必须使用 constructor 初始化一下
class Footer extends ComponentExt<Props, State> { constructor(props) { super(props) // 调用基类的所有的初始化方法 this.state = { visible: false, batchTime: 3, } } }
父子组件的传参props
父组件向子组件传递参数,子组件使用 props 接收
声明props参数的类型使用 propTypes ,类型分别有:array bool func number object string,node element 等等 isRequired 表示该值不能为空
声明props参数的默认值使用 getDefaultProps
var testAPP = React.createClass({ getInitialState:function(){ // 使用 getInitialState 声明state变量 return { testData: '父组件的变量' } }, render: function() { return ( <div> <h1>这是父组件开始传参</h1> <Template testData={this.state.testData} /> </div> ) } }) var template = React.createClass({ // 定义父组件传递参数的默认类型为String isRequired表示该值不能为空, propTypes:{ messages: React.PropTypes.string.isRequired, }, // 定义父组件传递参数的默认值 getDefaultProps: function () { return { testData: '这是默认的值' } }, render: function() { return ( <div> <h1>这是子组件props接收参数</h1> <p>{this.props.testData}</p> </div> ) } }) React.render( </TestAPP>, document.getElementById('app') )
事件处理
React事件绑定属性的命名采用驼峰式写法,而不是小写
获得原始的事件对象,使用 e.nativeEvent
阻止事件默认行为,使用 e.preventDefault()
var ClickApp = React.createClass({ getInitialState:function(){ return { clickCount: 0, } }, handleClick: function(e){ this.setState({ clickCount: this.state.clickCount + 1, }); // 获得完整的事件对象,而不是被封装过的 console.log(e.nativeEvent); }, render: function(){ return ( <div> <h2>点击下面按钮</h2> <button onClick={this.handleClick}>点击我</button> <p>你一共点击了:{this.state.clickCount}</p> </div> ) } }); var clickComponent = React.render( <ClickApp />, document.getElementById('app') )
DOM指向ref
将获得的refs对象转化为原生的DOM对象,使用 getDOMNode() 或者 React.findDOMNode()
ref 后面也可以接收一个函数 <div ref={ this.test() }><div>
获得子组件的方法也可以使用refs this.refs.name.test()
var FormApp = React.createClass({ handleSubmit:function() { console.log(this.refs.goodInput.getDOMNode().value) console.log(React.findDOMNode(this.refs['goodInput'].value)) }, render: function() { return ( <input ref="goodInput" type="text" defaultValue={this.state.inputValue }/> ) } })
双向数据流
React本身并不存在双向数据绑定,我们可以通过 react-with-addons 插件声明 mixins 模拟实现
var EasyForm = React.createClass({ mixins: [ React.addons.LinkedStateMixin ], // 引入 React.addons.LinkedStateMixin 插件 getInitialState:function(){ return { message: 'react is awesome!', isReactAwesome: true, } }, // 引入插件后拥有 this.linkState() 方法,模拟实现双向数据绑定 render:function(){ return ( <div> <input type="text" valueLink={this.linkState('message')} /> <input type="checkbox" checkedLink={this.linkState('isReactAwesome') } /> <br/> </div> ) } });
this.linkState() 可以作为参数传递到子组件,通过子组件改变父组件的值
var EasyForm = React.createClass({ mixins: [ React.addons.LinkedStateMixin ], getInitialState:function(){ return { message: 'react is awesome!', isReactAwesome: true, } }, render:function(){ return ( <div> <SubComp messageLink={ this.linkState('message') } likeLink={this.linkState('isReactAwesome')} /> </div> ) } }); var SubComp = React.createClass({ render:function(){ return ( <div> <h3>这是个子组件哦</h3> <SubSubComp {...this.props } /> </div> ) } }); var SubSubComp = React.createClass({ render:function(){ return ( <div> <p>你想说什么?</p> <input type="text" valueLink={ this.props.messageLink } /> <p>你稀罕React么?</p> <input type="checkbox" checkedLink = {this.props.likeLink } /> </div> ) } })
MIxins 方法共享
在不同的组件之间共用功能。共享代码,和页面一样具有生命周期
npm install react-mixin --save
const MixiLog = { componentDidMount () { console.log('Mixinlog componentDidMount') }, log () { console.log('这是Mixin的方法') } } export default MixiLog
import ReactMixin from 'react-mixin' // 引入react-mixin class AddLesson extends ComponentExt<Props, any> { constructor(props) { super(props) this.state = {} } test () { // 调用mixin里面的方法 MixiLog.log() } render() { const { lessonLineData } = this.props.classroomStore return ( <div className={classes()}> 这是组件 </div> ) } } ReactMixin(AddLesson.prototype, MixiLog) // 绑定mixin到该类的prototype export default AddLesson
生命周期
shouldComponentUpdate:function(nextProp,nextState){ console.log('shouldComponentUpdate'); if(nextState.count > 10) return false; return true; },
手动卸载React 对象,使用 React.unmountComponentAtNode() 接收一个DOM节点参数
killMySelf: function(){ React.unmountComponentAtNode( document.getElementById('app') ); },