💎一站式轻松地调用各大LLM模型接口,支持GPT4、智谱、星火、月之暗面及文生图 广告
[TOC] ## 前言 通过本文你将获得对react的基本了解,并希望你能够针对此做出正确的技术选型。 ## 框架特性 * 声明式设计 −React采用声明范式,可以轻松描述应用。 * 高效 −React通过对DOM的模拟,最大限度地减少与DOM的交互。 * 灵活 −React可以与已知的库或框架很好地配合。 * JSX − JSX 是 JavaScript 语法的扩展。React 开发不一定使用 JSX ,但我们建议使用它。 * 组件 − 通过 React 构建组件,使得代码更加容易得到复用,能够很好的应用在大项目的开发中。 * 单向响应的数据流 − React 实现了单向响应的数据流,从而减少了重复代码,这也是它为什么比传统数据绑定更简单。 ## 开始上手 ### 安装react 你可以通过cdn加载 ,比如下面的方式 ~~~ <script src="https://cdn.bootcss.com/react/15.4.2/react.min.js"></script> <script src="https://cdn.bootcss.com/react/15.4.2/react-dom.min.js"></script> <script src="https://cdn.bootcss.com/babel-standalone/6.22.1/babel.min.js"></script> ~~~ ### 通过npm加载 ~~~ $ npm install -g cnpm --registry=https://registry.npm.taobao.org $ npm config set registry https://registry.npm.taobao.org $ cnpm install -g create-react-app ~~~ ### 初始化react项目 该方法启动的项目支持实时更新修改到视图,入口是index.js文件,公共页面在public中的index.html,默认载入的页面为app.js文件。样式与组件为分离的。 ~~~ $ create-react-app my-app $ cd my-app/ $ npm start ~~~ 启动成功页面: ![启动成功页面](https://box.kancloud.cn/3e61b9ce47f7955a47a4df046d3e50dd_1088x736.png) **备注:** 如果提示你已经有3030端口占用,是否换一个端口,选择yes即可 ## 基本语法(参照官网) ### 组件 #### 三种组件类型 ##### **1.无状态纯样式函数组件,只是依赖prop展示内容** > **基本特点**: > 1 组件不会被实例化,整体渲染性能得到提升 > 因为组件被精简成一个render方法的函数来实现的,由于是无状态组件,所以无状态组件就不会在有组件实例化的过程,无实例化过程也就不需要分配多余的内存,从而性能得到一定的提升。 > 2 组件不能访问this对象 > 无状态组件由于没有实例化过程,所以无法访问组件this中的对象,例如:this.ref、this.state等均不能访问。若想访问就不能使用这种形式来创建组件 > 3 组件无法访问生命周期的方法 > 因为无状态组件是不需要组件生命周期管理和状态管理,所以底层实现这种形式的组件时是不会实现组件的生命周期方法。所以无状态组件是不能参与组件的各个生命周期管理的。 > 4 无状态组件只能访问输入的props,同样的props会得到同样的渲染结果,不会有副作用 > **使用建议**: > 被鼓励在大型项目中尽可能以简单的写法来分割原本庞大的组件,有可能的情况下尽可能用无状态组件 ~~~ function HelloComponent(props, /* context */) { return <div>Hello {props.name}</div> } ~~~ ##### **2.React.createClass** `React.createClass`是react刚开始推荐的创建组件的方式,这是ES5的原生的JavaScript来实现的React组件,属于有状态的组件,其形式如下: ~~~ var InputControlES5 = React.createClass({ propTypes: {//定义传入props中的属性各种类型 initialValue: React.PropTypes.string }, defaultProps: { //组件默认的props对象 initialValue: '' }, // 设置 initial state getInitialState: function() {//组件相关的状态对象 return { text: this.props.initialValue || 'placeholder' }; }, handleChange: function(event) { this.setState({ //this represents react component instance text: event.target.value }); }, render: function() { return ( <div> Type something: <input onChange={this.handleChange} value={this.state.text} /> </div> ); } }); ~~~ 备注: 特点是无论是否需要事件都要绑定在组件上,导致不必要的开销;混合函数mixin不够直观。 ##### **3.React.Component** 是以ES6的形式来创建react的组件的,是React目前极为推荐的创建有状态组件的方式,最终会取代React.createClass形式;相对于 React.createClass可以更好实现代码复用。 ~~~ class InputControlES6 extends React.Component { constructor(props) { super(props); // 设置 initial state this.state = { text: props.initialValue || 'placeholder' }; // ES6 类中函数必须手动绑定 this.handleChange = this.handleChange.bind(this); } handleChange(event) { this.setState({ text: event.target.value }); } } ~~~ ### 状态组件 除了使用外部传入的数据以外 (通过 this.props 访问传入数据), 组件还可以拥有其内部的状态数据 (通过 this.state 访问状态数据)。 当组件的状态数据改变时, 组件会调用 render() 方法重新渲染。在下面的代码实例中通过声明周期的钩子以及state实现了计时器显示。 ~~~ //构造器中必须实现super继承 否则拿不到this对象 constructor(props) { super(props); this.state={seconds:0} } ticker() { this.setState(prevState=>( { seconds :prevState.seconds+1 } )) } //组件渲染好时的钩子函数 componentDidMount() { this.interval=setInterval(()=>this.ticker(),1000) } <span >timer:{this.state.seconds}</span> ~~~ 在实现一个点击更改状态的代码,事件需要在构造器中绑定,另外需要注意的是标签中的数据或者事件需要加this,需要加大括号。 ~~~ constructor(props){ super(props); this.state={liked:false} this.change=this.change.bind(this) } change(){ this.setState({liked:!this.state.liked}) } render({ var text=this.state.liked?'喜欢':'不喜欢'; return ( {text} <button onClick={this.change}>点击切换</button> ) }) ~~~ ### todoList应用 使用事件,列表遍历,值的使用我们可以实现一个简单的todoList应用,代码如下:(需要注意的是: - 无论数据还是事件都需要用{}使用 - 事件需要显性的定义之后再绑定到构造器中 - 使用时需要申明是state中的还是prop中的 - 列表的循环用的是map的方式) ~~~ constructor(props){ super(props); this.state={text:'',items:[]} this.change=this.change.bind(this) this.submit=this.submit.bind(this) } change(e) { this.setState( { text:e.target.value } ) } submit(e){ e.preventDefault(); if (!this.state.text.length) { return; } const newItem = { text: this.state.text, id: Date.now() }; this.setState(prevState => ({ items: prevState.items.concat(newItem), text: '' })); } <h2>Todo list</h2> <ul> {this.state.items.map(item=>( <li key={item.id}>{item.text}</li> ) )} </ul> <input type="text" onChange={this.change} value={this.state.text}/><button onClick={this.submit}>添加items</button> ~~~ ![效果图](https://box.kancloud.cn/263b78217aa8bb57d83542d684bf3a56_930x374.png) ### 引入第三方库 React 的使用非常灵活,并且提供了可以调用其他第三方框架或库的接口。下面这个示例就使用了一个用来渲染 markdown 语法,名为 remarkable 的库。它可以实时转换渲染 `<textarea>` 里的内容。 ~~~ import Remarkable from "remarkable" constructor(props){ super(props); this.state={text:''} this.change=this.change.bind(this) } change(e) { this.setState( { text:e.target.value } ) } getRawMarkup() { const md = new Remarkable(); return { __html: md.render(this.state.text) }; } <textarea type="text" onChange={this.change} value={this.state.text}>{this.state.text}</textarea> <div dangerouslySetInnerHTML={this.getRawMarkup()}/> ~~~ ![小标题](https://box.kancloud.cn/eae3c44d9597287d6b9258ede77a5d32_1086x358.png) ## 调试工具 ### react-devtool [react-devtools](https://github.com/facebook/react-devtools) 你可以借助这个chrome的插件查看到react组件的周期以及状态,方便你进一步的开发。(这个插件需要重启浏览器才会生效) ### 其他 - [stackoverflow-reactjs](https://stackoverflow.com/questions/tagged/reactjs) - ## 相关教程 * [react官方教程](https://doc.react-china.org/tutorial/tutorial.html) * [阮一峰react教程](http://www.ruanyifeng.com/blog/2015/03/react.html) * [react-菜鸟教程](http://www.runoob.com/react/react-tutorial.html) * [react的简单教程](https://github.com/ruanyf/react-demos) * [react-issues](https://github.com/facebook/react/issues) ## 相关ui框架 * [ant-mobile](https://mobile.ant.design/index-cn) * [ant-design(pc)](https://ant.design/index-cn)