ThinkChat2.0新版上线,更智能更精彩,支持会话、画图、阅读、搜索等,送10W Token,即刻开启你的AI之旅 广告
[TOC] ## 前言 本文重点学习理解react组件部分,文档内容来源于react官网以及《react全栈》。本文内容仅针对react初学者,请大神略过,仅限于读书笔记与摘录。 本文节选 第三章第四节组件部分,建议阅读时间:20-30min ## 概述 组件是react的基石,所有的react程序都应该是基于组件的。 ## 序 在之前是通过react.creatClass来实现定义类的,在支持了es6之后,我们通过class写法以及构造器的部分简化了很多。比如一个简单的组件可能是这样写的:可以看到类属性之间不用加逗号,构造器里就可以实现state的初始化等便利的操作。 ~~~ import React from ‘react' class List extends React.Component { constructor (){ super(); this.state=[‘a’,”b”,”c’]; } render (){ retrurn (…); } } ~~~ ## Props 注入属性,一般是从外组件或者外界条件传入的初始化数值,一般是基础数据类型。其中通过this.props 来获取相关的属性值 ~~~ <h1>我的名字是:{this.props.name}</h1> //有了组件之后可以通过ReactDom 来把组件渲染到dom节点上。它的操作是 : import {render} from ‘react-dom' const props= { name :"nike", age :’20' } Render(<compName {…props}>,document.getElementById(“container")) ~~~ 当程序结构变的复杂的时候 需要对传入属性做类型匹配的判断,我们可以根据PropTypes 来判断 ~~~ import {PropTypes } from ‘react' const proTypes= { optionalArray :PropTypes.array, optionalBool:PropTypes.bool, optionalFun:PropTypes.func, optionalNumbber:PropTypes.number, optionalObject:PropTypes.object, optionalString:PropTypes.string, //可以是一个reactElement 类型的 optionElement :PropTypes.element, //可以是别的组件的实例 optionalMessage:PropTypes.instanceOf(message), //可以规定为一组中的一个 optionalsEnum:PropTypes.oneof([“news”,”photos”]), //可以是规定的一组类型中的一个 optionalUnion:PropTypes.oneOfType([PropTypes.string,PropTypes.number,PropTypes.instanceOf(Message)]) } //了解了这么多属性工具之后,我们尝试的给我们的组件属性加上验证, Import React,{PropTypes} from ‘react' //需要验证的属性 const proptypes = { name : PropTypes.string.isRequired, age:PropTypes.number.isRequired } class Profile extends React.component { render ( ){ return ( <div class=“profile-component"> <h1>我的名字是{this.props.name}</h1> <h1>年龄是:{this.props.age}</h1> </div> ) } } Profile.proptypes = proptypes export default Profile ~~~ ## State 组件是组件内部的属性,组件本身是一个状态机,可以在构造函数中直接定义它的值,然后根据这些值渲染不同的ui,当state发生变化的时候,可以通过this.setState 来触发render方法,重新渲染新的ui. 假如我们需要加一个点赞的按钮,那么 我们的按钮需要绑定事件. ~~~ <button onClick=“this.likedCallBack”>给我点赞</button> <span>总点赞数:{this.state.liked}</span> ~~~ 在构造函数中绑定当前对象,自定义函数不会被绑定到实例上,所以需要手动在constructor里面绑定。 ~~~ constructor (){ this.linkedCallBack = this.likedCallBack.bind(this); } likedCallBack(){ let liked = this.state.liked; liked++; //利用了对象属性的缺省写法 可以写入一个回调函数 , //这样在某些特定场景的时候不需要额外写自己的钩子或者异步编程了 this.setState({ Liked },callBack) } ~~~ ## 组件的生命周期 每个组件都有自己的声明周期,react用不同的方法来描述它的生命周期,我们可以称为钩子函数, 生命周期如下 : - 组件初始化 getDefaultProps >getInititalState> componentWillMount> render> componentDidMount - 组件props更新 : componentWillReceiveProps >shouldComponentUpdate> componentWillUpdate> render > componentDidUpdate - 组件卸载: componentWillUnmount ## 组合组件 一个组件可以包含多个其他组件,比如 新建一个爱好的组件 ~~~ import React,{ PropTypes} from ‘react' const proptypes = { Hobby :PropTypes.string.isRequired } class hobby extends React.component{ render (){ return <li>this.props.hobbby</li> } } Hobby.proptypes = proptypes export default Hobby ; ~~~ ~~~ //在我的简历组件中 //Profile.jsx import Hobby from “./hobby" ... class Profile extends React.component{ constructor(){ super(); this.state={ liked:0; hobbies:[‘游泳’,’洗澡‘]} } render (){ return { {this.state.hobbies.map((hobby,i)=><hobby key={I} hobby={hobby}/>)} //注意给每个循环加唯一的key } } } ~~~ ## 无状态函数组件 没有复杂的state状态机需求,不需要生命周期函数,那么可以吧这个组件定义为一个纯函数组件,stateless functional component也就说只是根据需要生成组件,没有其他的副作用,而且简单明了。 比如刚才的爱好组件可以写成这样的。这个写法是react推荐的 ~~~ function Hobby (props){ return <li>{props.hobby}</li> } export default Hobby ~~~ ## state设计原则:最小化state原则 尽量把尽可能多的组件设计为无状态组件,把变动的部分集中到几个核心的变化组件的state处理中。比如:商品列表,选中的商品列表。 分析如下: 可以从state计算中的得到的展示,写到state中。 组件并不需要保存到state中,只需要render方法中渲染即可 props中的数据,可以看做组件的数据来源,因此也不需要保存在state中 ## dom操作 我们大多数情况直接用setState获取值,但某些情况还是需要dom操作的,那么这个时候可以通过ref实现,在源上定义ref=’targetName’ 然后使用的时候 ~~~ let hobbyInput = this.refs.targetName let hobby = hobbyInput.value ~~~ ## 待探索内容 - react的dom是否支持链式操作? - refs的实现机制是什么 ## 参考文档 - 《react全栈》张轩 杨寒星著 - 《深入react技术栈》