react基础教程---旧版
React基础教程(旧版):React教程旧版
【1】React知识点:React基础、全家桶、ReactNative
【2】讲解方式:从最基础搭建环境开始,按照知识点进行介绍,这样减少在工作中的出错频率,增加排查错误能力和解决效率。
大纲:
React-01课程介绍 React-02环境搭建和HelloWorld程序 React-03初识JSX语法 React-04进阶JSX语法 React-05t组件state成员 React-06Props和Render React-07组件的生命周期 React-08组件小实例 React-09this.props.children React-10组件的属性验证 React-11ref获取真实DOM节点 React-12表单bind复用 React-13表单name复用 React-14表单的可控组件 React-15表单的不可控组件
(1)React-01课程介绍
特点:
1、虚拟DOM(Virtial DOM) 2、组件化(将项目按照功能进行横向划分)
3、React单向数据绑定,详见React的单向数据流与Vue的双向绑定.
(2)React-02环境搭建和HelloWorld程序
链接:https://github.com/facebook/react/releases?after=16.1.0-beta
下载对应代码库,然后在项目引入
注意: 1、createClass写法是在V15版本之前的写法,V16开始摒弃了 2、因为页面无法直接解析,所以需要通过babel解析。但这里的 babel主要依赖第三方包配合解析
组件化与组件提取
组件化概念:
首先要了解一点:在React里,整体就是一个组件化设计,增强可复用性和维护性
对比之前的简单数据、XML嵌套数组,这里我们再次加大数据复杂度
这里会看到JSX的render里的return方法使用了(),详解React之JSX里render中return方法添加括号()或者[].
此时render的第一个参数优点累赘繁多,所以接下来举个案例,将其提取出去
我们可以看到,setInterval定时器里调用函数时没有加函数执行符(),详解浅谈JS之常问问题:setInterval和setTimeout调用函数为什么不加小括号()???.
接下来看下组件化,首先创建组件,React里创建组件有两种方法,如下所示
注意: 这里因为React的相关依赖包版本问题,我们换用其他版本(V16之前的版本)去进行测试,将之前的依赖包一一替换掉 <script src="http://static.runoob.com/assets/react/react-0.14.7/build/react.min.js"></script> <script src="http://static.runoob.com/assets/react/react-0.14.7/build/react-dom.min.js"></script> <script src="http://static.runoob.com/assets/react/browser.min.js"></script>
1、第一种方法为React.createClass({})
2、第二种方法为ES的class...extends...(ES6里Class 可以通过 extends 关键字实现继承)
当然,构造器constructor主要用来
来构造默认的属性和状态,这里可以省略
如上所示我们将上个案例进行组件化抽离
(3)React-03初识JSX语法
加入我们没有接触过JSX,那么之前的组件写法如下
第一行是创建组件
第二行是将组件进行转换渲染
缺点:纯JS操作,较为繁琐
接下来介绍下JSX语法:
Javascript and XML
之前的纯JS操作,虽然较为繁琐,但可以完成react所有操作。缺点较多:JS和标签混写在一起,缺乏模板的支持,写法很不友好。而JSX便可以很好解决这个问题
JSX语法需要Babel转换,所以在学习阶段,在客户端浏览器上进行测试时,需要结合browser.min.js或者browser.js进行转换预览。
注意:
这种browser.min.js渲染编译方法效率较低,仅仅在开发学习阶段使用,正式工作开始一般不用
babel的CDN链接:https://www.bootcdn.cn/babel-core/
注意:不建议使用babel6.xxx以上版本,可能不再支持在线转换,所以使用5.xxx版本
对比JSX于之前JS的区别 1、scrpit的type变为text/babel 2、js创建元素,变为直接写html元素,较为直观方便
拓展:live-server静态服务器启动预览
live-server优点:热更新
详见文章web服务器live-server(热更新)的安装及使用.JSX支持表达式和动态传至,如下所示
同时还支持三目运算符(三元表达式)、二目运算符(二元表达式)详见三元表达式(三目运算符)和二元表达式(二目运算符).、map遍历等... ...
注意: 三元表達式和二元表达式都可以使用去取代if...else if ...else和if..else语法,但不支持if...else语法
(4)React-04进阶JSX语法
JSX支持遍历语法,如下
除了上面数组遍历方式,还有另一种,如下所示
结合for循环(外部)
注意:
主流循环写法是 map,jsx里面不能用for循环,因为for循环不是表达式。
可以用Array::map方法,注意给返回的每一个组件设置一个唯一的key。详见React之JSX循环遍历方法对比.
(5)React-05t组件state成员
组件的通俗理解:
可以看作一个带有props属性集合、state状态集合、并且构造出一个虚拟DOM结构的对象
React最主要的创新就是将组件看成状态集合,用户界面的不同是根据状态进行渲染的,状态跟数据保持一致,类似于Vue,但Vue是数据驱动界面.
React开发时主要也是针对state状态进行创建和更改操作
单向数据绑定:从这里可以看出React不同于Vue,为单向数据绑定,修改需要通过setState
注意:这里事件绑定必须用小驼峰法,因为JS对大小写敏感,HTML对大小写不敏感。
(6)React-06Props和Render
首先了解下HTML的props,如下所示,input元素的属性便可以称之为input的props
<input type="text"> 这里type="text"便是props属性
接下来看下React的props属性
设计组件时需要考虑哪些是props属性集合,哪些是state状态集合
props:从父组件传递过来,例如类名、回调响应函数等
state:组件渲染时进行改变,或者生命周期操作的
1、render是纯粹的
即render内部不建议放逻辑操作,state操作和方法应该放置到生命周期等等
(7)React-07组件的生命周期/钩子函数
组件的生命周期也可以称之为钩子函数,主要包含挂载阶段、更新阶段、销毁阶段... ...
案例如下:
接下来进行渲染
测试如下
接下来点击按钮,更新state,如下所示
(8)React-08组件小实例
该案例包含组件的属性props、状态state、生命周期等... ...,做一个字体闪动效果
等待组件加载完毕,开始闪动,结合生命周期componentDidMount
组件声明完毕,开始渲染DOM
测试如下
...
1、什么时候使用state? 需要在组件里进行更改变化的,最好使用state 2、什么时候用props? 由父组件传递给字组件,不在字组件内部进行更改
3、为什么用生命周期?
在React的组件里,render必须是纯粹的,不能有业务逻辑代码,尽量将业务逻辑代码放到生命周期钩子里.
(9)React-09组件的this.props.children组件内部所有子节点
注意点:
this.props对象的属性与组件的属性一一对应,但有一个例外,就是this.props.children属性,它表示组件里的所有子节点
案例如下
结果如下:
(10)React-10组件的属性验证
作用:对外界父组件传递过来的属性进行限定,例如希望name属性不可缺少且为字符串... ...,对此React引入了PropsTypes属性
结果如下
注意:
该警告只在开发模式下管用,生产模式下不再应用
props默认值
如果父元素没有传递props,则会显示默认值。如果传递了则会覆盖默认值
(11)React-11ref获取真实DOM节点
类似于Vue,React里同样应用了虚拟DOM技术。只有在组件挂在完毕后,才会渲染出真实DOM节点。
案例:点击按钮时,将光标定位到输入框
要求:点击按钮,输入框聚焦
此时点击按钮,便可以实现输入框聚焦
(12)React-12表单bind复用
效果如下:
接下来进行state状态初始化
接下来进行表单事件绑定,因为每次绑定语法差不多,所以这里我们借用bind实现语法抽离
关于bind复用,在React表单里应用较为频繁。此时,可以在控制台进行监控
接下来进行表单提交处理,如下所示
(13)React-13表单name复用
上面案例是在表单利用bind进行复用,接下来利用name进行复用
主要语法和之前类似,稍微修改即可,如下所示
此时也不用bind绑定了
完整代码如下:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <!-- Load React. Note: when deploying, replace "development.js" with "production.min.js" <script src="https://unpkg.com/react@16/umd/react.development.js" crossorigin></script> <script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js" crossorigin></script> --> </head> <body> <div id="root"></div> <script src="./dist/react.js"></script> <script src="./dist/react-dom.js"></script> <script src="./dist/browser.js"></script> <script type="text/babel"> // 定义组件 var FormComponent = React.createClass({ getInitialState(){return {name:'',location:'tj',confirm:false}}, handleChange(e){ let newState = {} newState[e.target.name] = e.target.name == "confirm" ? e.target.checked : e.target.value; this.setState(newState) }, handleSubmit(e){ e.preventDefault() let {name,location,confirm} = this.state var confirmValue = confirm == true ? '同意':'不同意' alert(name+location+confirm) }, render(){ let {name,location,confirm} = this.state return ( <form onSubmit={this.handleSubmit}> <label htmlFor="name">姓名:</label> <input id="name" type="text" name="name" onChange={this.handleChange} value={name}/><hr/> <label>祖籍:</label> <select name="location" value={location} onChange={this.handleChange}> <option value="sjz">石家庄</option> <option value="bj">北京</option> <option value="tj">天津</option> </select><hr/> <input id="confirm" type="checkbox" name="confirm" onChange={this.handleChange} checked={confirm}/> <label htmlFor="confirm">您已经阅读相关条款并同意</label><hr/> <button>提交</button> </form> ) } }) // DOM渲染 ReactDOM.render(<FormComponent />,document.getElementById("root")) </script> </body> </html>
实现name复用的关键
对比与bind复用,name复用要求每个元素必须加入name属性
(14)React-14表单的可控组件
小结:input中的value绑定到state状态的React组件就是可控组件,否则是不可控组件.
此时的input不可以编辑和删除
接下来添加事件监听,便成了可控组件,可以编辑和删除input内容
可控组件的两个特点:1、value绑定state状态集合;2、事件绑定,实时监控onChange事件.
(15)React-15表单的不可控组件
一般日常开发都推荐使用可控组件,某些情况下也可以使用不可控组件
如上所示,一个简单的input控件,只要不绑定value,便可以视为不可控组件
接下来通过绑定方法获取该组件具体值,如下所示
如果给不可控组件添加alue,则如下所示
测试后会发现,由于React的渲染策略,这里的value无法再进行编辑删除等操作,那么不可控组件的默认值如何实现呢?此时需要用到defaultValue属性,如下所示
此时便可以正常编辑
小结:
不可控组件的默认值使用defaultValue属性实现,通过ref获取控件值
..