react学习笔记一:入门级小白到脚手架(create-react-app)开发项目
文章目录
- 前言
- 一、helloworld
- 二、React jsx
- 2.1 jsx
- 2.2 动态展示列表数据
- 2.3 虚拟dom创建的两种方式
- 2.4 代码实例
- 2.5 步骤
- 2.6 技术点
- 三、组件化、模块化
- 3.1 组件
- 3.2 组件化
- 3.3 模块
- 3.4 模块化
- 四、组件定义两种方式
- 3.1 代码实例
- 3.2 技术点
- 五、组件三个属性:state、props、refs
- 3.1 component_state
- 3.1.1 需求说明
- 3.1.2 state
- 3.1.2 代码实例
- 3.1.3 步骤
- 3.1.4 步骤、技术点
- 3.2 component_props
- 3.2.1 需求说明
- 3.2.2 props
- 3.2.3 代码实例
- 3.2.4 步骤、技术点
- 3.2.5 问题:区别state和props
- 3.3 component_refs
- 3.3.1 需求描述
- 3.3.2 refs属性
- 3.3.3 事件处理
- 3.3.4 强烈注意
- 3.3.5 代码实例
- 3.3.6 步骤、技术点
- 六、组件的组合
- 6.1 需求描述
- 6.2 代码实例
- 6.3 技术点(==注意:数据在哪,操作方法就在哪==)
- 6.4 React工具使用,查看三个属性
- 6.5 功能界面的组件化编码流程(无比重要)
- 七、收集表单数据
- 7.1 需求描述
- 7.2 理解
- 7.3 代码实例
- 7.4 步骤、技术点
- 八、组件生命周期
- 8.1 需求效果
- 8.2 理解
- 8.3 生命周期流程图
- 8.4 生命周期详述
- 8.5 重要的勾子
- 九、虚拟DOM与DOM Diff算法
- 9.1 代码实例
- 9.2 基本原理图
- 十、react引用(基于react脚手架)
- 10.1 使用create-react-app创建react应用
- 10.1.1 react脚手架
- 10.1.2 创建项目并启动
- 10.1.3 react脚手架项目结构
- 10.2 项目结构
- 10.2 demo:评论管理
- 10.3 demo:评论管理
- 十一、react ajax
- 11.1 理解
- 11.1.1 前置说明
- 11.1.2 常用的ajax请求库
- 11.1.3 效果
- 11.1.4 代码实例
- 11.2 axios
- 11.2.1 文档
- 11.2.1 相关API
- 11.3 demo: github users
- 11.3.1 需求描述
- 11.3.2 拆分组件
- 11.3.3 代码实例
- 11.4 Fetch
- 11.4.1 文档
- 11.4.2 相关API
- 十二、几个重要技术总结
- 12.1 组件间通信
- 12.1.1 方式一: 通过props传递
- 12.1.2 方式二: 使用消息订阅(subscribe)-发布(publish)机制
- 12.1.3 方式三: redux
- 12.2 事件监听理解
- 12.2.1 原生DOM事件
- 12.2.2 自定义事件(消息机制)
- 12.3 ES6常用新语法
- 十三、react-router
- 13.1 项目理解
- 13.1.1 react-router的理解
- 13.1.2 SPA的理解
- 13.1.3 路由的理解
- 13.1.4 前端路由的实现
- 13.2 react-router相关API
- 13.2.1 react-router组件
- 13.2.2 其它
- 13.3 基本路由使用
- 13.3.1 效果
- 13.3.2 准备
- 13.4 嵌套路由使用
- 13.4.1 效果
- 13.5 向路由组件传递参数数据
- 13.5.1 效果
- 13.6 多种路由跳转方式(==重要==)
- 13.6.1 效果
- 13.6.2 代码实例
- 十四、React UI
- 14.1 最流行的开源React UI组件库
- 14.1.1 material-ui(国外)
- 14.1.2 ant-design(国内蚂蚁金服)
- 14.2 ant-design-mobile使用入门
- 14.2.1 效果
- 14.2.2 使用create-react-app创建react应用
- 14.2.3 搭建antd-mobile的基本开发环境
- 7.2.4. 实现按需打包(组件js/css)
- 扩展,数组方法
- 1. map()
- 2. unshift()
- 3. splice()
- 4. filter()
前言
公司实习的地方,使用react,然后打算学习一下react,并把基础知识点整理一下,毕业设计的前端,也使用react来搭建前端框架。
这里主要有如下react基础知识点:
- jsx语法
- 组件定义的两种方式:类和方法
- 组件三大属性:state、props、ref(这个为标签属性)
- 组件的组合
- 标签的受控组件和非受控组件
- react的生命周期
- react应用(基于create-react-app脚手架)
- react-axios
- react-router
- react-UI:antdesign
最重要的一个 没讲:redux
代码都已上库到GitHub上。
传送门: https://github.com/fengfanli/react-study
一、helloworld
先使用react写一个helloworld,体验一下。
先导入react开发版本js,有三个,react.development.js、react-dom.development.js、babel.min.js
react.js:React 的核心库
react-dom.js:提供操作DOM 的react 扩展库
babel.js:为babel库,两个作用1、将es6语法转化为es5,2、解析JSX语法代码为纯JS 语法代码的库(这里使用的是后者语法)
<body><div id="example"></div><script type="text/javascript" src="../js/react.development.js"></script><script type="text/javascript" src="../js/react-dom.development.js"></script><script type="text/javascript" src="../js/babel.min.js"></script><script type="text/babel"> // 声明:告诉babel.js这里有jsx语法// 1、创建虚拟DOM元素对象var vDom = <h1>Hello React</h1> // 不是字符串 jsx 语法// 2、将虚拟DOM渲染到页面真实DOM容器中ReactDOM.render(vDom, document.getElementById("example"))</script>
</body>
页面:
步骤(重点学习的地方):
在< script type=“text/babel”> 中编写:声明:告诉babel.js这里有jsx语法
2. 创建虚拟DOM元素对象:就是定义一个变量,将HTML标签赋值于变量
3. 将虚拟DOM渲染到页面真实DOM容器中
技术点:
- jsx语法:
var vDom = <h1>Hello React</h1>
- 渲染语法:
ReactDOM.render(vDom, document.getElementById("example"))
二、React jsx
2.1 jsx
- 全称: JavaScript XML
- react定义的一种类似于XML的JS扩展语法: XML+JS
- 作用: 用来创建react虚拟DOM(元素)对象
a. var ele = < h1>Hello JSX!< /h1>
b. 注意1: 它不是字符串, 也不是HTML/XML标签
c. 注意2: 它最终产生的就是一个JS对象 - 标签名任意: HTML标签或其它标签
- 标签属性任意: HTML标签属性或其它
- 基本语法规则
a. 遇到 <开头的代码, 以标签的语法解析: html同名标签转换为html同名元素, 其它标签需要特别解析
b. 遇到以 { 开头的代码,以JS语法解析: 标签中的js代码必须用{ }包含 - babel.js的作用
a. 浏览器不能直接解析JSX代码, 需要babel转译为纯JS的代码才能运行
b. 只要用了JSX,都要加上type=“text/babel”, 声明需要babel来处理
2.2 动态展示列表数据
功能: 在页面中遍历一个数组,将其显示在页面中。
问题: 如何将一个数据的数组 转换为 一个标签的数组 很常用,使用数组的map() 方法 和 箭头函数
<div id="example1"></div><script type="text/javascript" src="../js/react.development.js"></script><script type="text/javascript" src="../js/react-dom.development.js"></script><script type="text/javascript" src="../js/babel.min.js"></script><script type="text/babel">/*** 功能:动态展示列表数据* 问题:如何将一个数据的数组 转换为 一个标签的数组 很常用* 使用数组的map() 方法 和 箭头函数* */const names = ['jQuery', 'zepto', 'angular', 'react', 'vue']// 1、创建虚拟DOM// li 标签一定要带 key属性,而且还不能一样 否则警告const ul = (<ul>{names.map(name=> <li key={name}>{name}</li>)}</ul>)// 2、渲染虚拟DOMReactDOM.render(ul, document.getElementById('example'))</script>
页面:
步骤:
- 创建虚拟DOM
使用 {} 大括号写法,在里面写js语法,将数组遍历。 - 渲染虚拟DOM(固定形式写法,将定义好的jsx虚拟dom渲染到 真实dom上)
技术点:
3. {} 大括号写法:
4. 数组方法map():js方法,是对数组的遍历,里面为回调函数,方法形式:
map(value)
:value 为数组的值,
map(value, index)
:value 为数组的值,index为数组下标
2.3 虚拟dom创建的两种方式
- 使用原生js方法:const vDom1 = React.createElement(‘h1’, {id:‘myTitle’},‘hello’)
- 使用jsx方法:const vDom2 = < h3 id={myId.toUpperCase()}>{msg.toLowerCase()}< /h3>
2.4 代码实例
<body><div id="test01"></div><div id="test02"></div><script type="text/javascript" src="../js/react.development.js"></script><script type="text/javascript" src="../js/react-dom.development.js"></script><script type="text/javascript" src="../js/babel.min.js"></script><script type="text/javascript">/*** 需求,两种方式实现虚拟DOM的创建* 1、使用原生js方法:const vDom1 = React.createElement('h1', {id:'myTitle'},'hello')* 2、使用jsx方法:const vDom2 = <h3 id={myId.toUpperCase()}>{msg.toLowerCase()}</h3>*/const msg = 'I Like you!'const myId = 'fengfanli'// 1、创建虚拟DOM元素对象// const element = React.createElement('h1', {id:'myTitle'},'hello')const vDom1 = React.createElement('h2', {id: myId.toLowerCase()}, msg.toUpperCase())// debugger// 2、将虚拟DOM渲染到页面真实DOM容器中ReactDOM.render(vDom1, document.getElementById('test01'))</script><script type="text/babel">// 1、创建虚拟DOM元素对象const vDom2 = <h3 id={myId.toUpperCase()}>{msg.toLowerCase()}</h3>// debugger// 2、将虚拟DOM渲染到页面真实DOM容器中ReactDOM.render(vDom2, document.getElementById('test02'))</script>
</body>
页面:
2.5 步骤
- 创建虚拟dom
- 渲染虚拟dom
2.6 技术点
- 渲染虚拟dom的两种方法:原生js和jsx
三、组件化、模块化
3.1 组件
- 理解: 用来实现特定(局部)功能效果的代码集合(html/css/js)
- 为什么: 一个界面的功能更复杂
- 作用: 复用编码, 简化项目编码, 提高运行效率
3.2 组件化
当应用是以多组件的方式实现, 这个应用就是一个组件化的应用。
3.3 模块
- 理解: 向外提供特定功能的js程序, 一般就是一个js文件
- 为什么: js代码更多更复杂
- 作用: 复用js, 简化js的编写, 提高js运行效率
3.4 模块化
当应用的js都以模块来编写的, 这个应用就是一个模块化的应用
四、组件定义两种方式
- 方式一:使用方法定义,没有状态用此种方式(简单组件)
- 方式二:使用类定义,(复杂组件)
3.1 代码实例
<body><div id="example1"></div><div id="example2"></div><script type="text/javascript" src="../js/react.development.js"></script><script type="text/javascript" src="../js/react-dom.development.js"></script><script type="text/javascript" src="../js/babel.min.js"></script><script type="text/babel">/*** 组件定义的两种方式* 1、使用方法定义,没有状态用此种方式(简单组件)* 2、使用类定义,(复杂组件)*/// 1.定义组件//方式1: 工厂函数组件(简单组件):没有状态的组件function MyComponent() {return <h2>工厂函数组件(简单组件)</h2>}//方式2: ES6类组件(复杂组件)class MyComponent2 extends React.Component{render(){console.log(this)return <h2>工厂函数组件(简单组件)</h2>}}// 2.渲染组件方式ReactDOM.render(<MyComponent />, document.getElementById('example1'))ReactDOM.render(<MyComponent2 />, document.getElementById('example2'))</script>
</body>
页面:
3.2 技术点
- 两种定义组件的方式:方法(简单组件)、类(复杂组件)
- render()方法,在里面写UI,
五、组件三个属性:state、props、refs
3.1 component_state
3.1.1 需求说明
自定义组件,功能说明如下
- 显示 h2 标题,初始文本为:你喜欢我
- 点击标题更新为:我喜欢你
3.1.2 state
state是组件对象最重要的属性, 值是对象(可以包含多个数据)
组件被称为"状态机", 通过更新组件的state来更新对应的页面显示(重新渲染组件)
初始化状态:
constructor (props) {super(props)this.state = {stateProp1 : value1,stateProp2 : value2}}
- 读取某个状态值
this.state.statePropertyName
// statePropertyName 自定义名称 - 更新状态---->组件界面更新
this.setState({stateProp1 : value1,stateProp2 : value2})
3.1.2 代码实例
<body><div id="example"></div><script type="text/javascript" src="../js/react.development.js"></script><script type="text/javascript" src="../js/react-dom.development.js"></script><script type="text/javascript" src="../js/babel.min.js"></script><script type="text/babel">/*** 需求:自定义组件,功能说明如下* 1. 显示 h2 标题,初始文本为:你喜欢我* 2. 点击标题更新为:我喜欢你* */// 1.定义组件class Like extends React.Component{// 2)、构造器constructor(props){super(props)// 初始化状态this.state = {isLikeMe: false}// 将新增方法中的this 强制绑定为组件对象this.handleClick = this.handleClick.bind(this)}// 1)、重写组件类的方法render(){// 读取状态const {isLikeMe} = this.state // 第二种方式return <h2 onClick={this.handleClick}>{isLikeMe?'你喜欢我':'我喜欢你'}</h2>}// 3)、新添加的方法:内部的 this 默认不是组件对象,而是 undefined, 所以要在 构造器中 绑定方法handleClick(){console.log('handleClick()',this)// 得到原有状态 并取反const isLikeMe = !this.state.isLikeMe//更新状态this.setState({isLikeMe})}}// 2.渲染组件ReactDOM.render(<Like />, document.getElementById('example'))
</script>
</body>
3.1.3 步骤
- 定义组件类。
- 编写**render()**方法,在这里写UI组件。
- 编写构造器,和里面的state属性初始化。
- 然后在编写点击事件,这里需要注意这个方法需要绑定到类上,在构造器上进行bind()方法绑定。
3.1.4 步骤、技术点
- 编写组件类
- render方法
- constructor构造器、state属性
- 编写点击事件,在构造器bind绑定,注意更新state的方法和获取state的关键字
- 渲染组件:ReactDOM.render()
3.2 component_props
3.2.1 需求说明
需求: 自定义用来显示一个人员信息的组件
1). 姓名必须指定
2). 如果性别没有指定, 默认为男
3). 如果年龄没有指定, 默认为18
3.2.2 props
理解
- 每个组件对象都会有props(properties的简写)属性
- 组件标签的所有属性都保存在props中
作用
- 通过标签属性 从组件外向组件内 传递变化的数据
- 注意: 组件内部不要修改props数据
编码操作
- 内部读取某个属性值
this.props.propertyName
- 对props中的属性值进行类型限制和必要性限制
Person.propTypes = {
name: React.PropTypes.string.isRequired,
age: React.PropTypes.number.isRequired
}
- 扩展属性: 将对象的所有属性通过props传递
<Person {...person}/>
- 默认属性值
Person.defaultProps = {
name: 'Mary'
}
- 组件类的构造函数
constructor (props) {
super(props)
console.log(props) // 查看所有属性
}
3.2.3 代码实例
<body>
<div id="example1"></div>
<div id="example2"></div>
<div id="example3"></div>
<script type="text/javascript" src="../js/react.development.js"></script>
<script type="text/javascript" src="../js/react-dom.development.js"></script>
<script type="text/javascript" src="../js/prop-types.js"></script>
<script type="text/javascript" src="../js/babel.min.js"></script>
<script type="text/babel">/*** props属性 和 prop-types.js prop-types.js: 对值进行设定* 需求:自定义用来显示一个人员信息的组件,效果如页面,说明* 1、如果性别没有指定,默认为男* 2、如果年龄没有指定,默认为18*/// 1、定义组件/*** 使用 对象组件* 组件对象有三个 state props refs**/class Person extends React.Component{render(){console.log(this)return(<ul><li>姓名:{this.props.name}</li><li>年龄:{this.props.age}</li><li>性别:{this.props.sex}</li></ul>)}}// 指定属性 默认值Person.defaultProps = {age: 18,sex: '男'}// 对 props 中的属性值进行类型限制和必要性限制Person.propTypes = {name: PropTypes.string.isRequired,age: PropTypes.number}// 2、渲染组件const p1 = {name: 'Tom',age: 18,sex: '女'}ReactDOM.render(<Person name={p1.name} age={p1.age} sex={p1.sex} />, document.getElementById("example1"))const p2 = {name: 'Jack',}ReactDOM.render(<Person name={p2.name} age={20} />, document.getElementById("example2"))/*** ... 的作用* 1、打包* function fn(...as){} fn(1, 2, 3) : 打包的意思* 2、解包* const arr1 = [1, 2, 3] const arr2 = [6, ...arr1, 9] :解包的意思** @type {{name: string}}*/const p3 = {name: 'Feng',}ReactDOM.render(<Person {...p3} />, document.getElementById("example3"))
</script>
</body>
页面:
3.2.4 步骤、技术点
新添加了一个js:prop-types,这个库是在子组件中,对父组件传给子组件的属性值进行加以设定。
- 在渲染虚拟dom,
ReactDOM.render(<Person />, document.getElementById("example3"))
向 HTML标签一样,添加属性,往里面传值,在组件类 Person中通过this.props.属性名
获取值。 - 扩展运算符(三点运算符)
...
:将对象的所有属性通过props传递
3.2.5 问题:区别state和props
请区别一下组件的props和state属性
- state: 组件自身内部可变化的数据
- props: 从组件外部向组件内部传递数据, 组件内部只读不修改
3.3 component_refs
3.3.1 需求描述
需求: 自定义组件, 功能说明如下:
- 点击按钮, 提示第一个输入框中的值
- 当第2个输入框失去焦点时, 提示这个输入框中的值
3.3.2 refs属性
组件内的标签都可以定义ref属性来标识自己
a.<input type="text" ref={input => this.msgInput = input}/>
b. 回调函数在组件初始化渲染完或卸载时自动调用在组件中可以通过
this.msgInput
来得到对应的真实DOM元素作用: 通过ref获取组件内容特定标签对象, 进行读取其相关数据
3.3.3 事件处理
- 通过onXxx属性指定组件的事件处理函数(注意大小写)
a. React使用的是自定义(合成)事件, 而不是使用的原生DOM事件
b. React中的事件是通过事件委托方式处理的(委托给组件最外层的元素) - 通过event.target得到发生事件的DOM元素对象
<input onFocus={this.handleClick}/>
handleFocus(event) {
event.target //返回input对象
}
3.3.4 强烈注意
组件内置的方法中的this为组件对象
在组件类中自定义的方法中this为null
a. 强制绑定this: 通过函数对象的bind()
b. 箭头函数(ES6模块化编码时才能使用)
3.3.5 代码实例
<body>
<div id="example1"></div>
<script type="text/javascript" src="../js/react.development.js"></script>
<script type="text/javascript" src="../js/react-dom.development.js"></script>
<script type="text/javascript" src="../js/prop-types.js"></script>
<script type="text/javascript" src="../js/babel.min.js"></script>
<script type="text/babel">/*** 事件 与 ref* 需求:自定义组件,功能说明* 1、界面如图所示* 2、点击按钮,提示第一个输入框中的值* 3、当第二个输入框失去焦点时,提示这个输入框中的值*/// 1、创建组件class MyComponent extends React.Component {constructor(props) {super(props)this.showInput = this.showInput.bind(this)this.handleBlur = this.handleBlur.bind(this)}showInput() {const value = this.refs.content.value;alert(value)alert(this.input.value)}// 事件都有一个固定的形参handleBlur(event) {console.log(event)console.log(event.target) //指的是标签// event.target : 指的是 input 表单框alert(event.target.value)}/* 最后一个比较特别,操作的 dom 元素,是发生事件的元素。*/render() {return (<div><input type="text" ref="content"/> <input type="text" ref={input => this.input = input}/> <button onClick={this.showInput}>提升输入</button> <input type="text" onBlur={this.handleBlur} placeholder="失去焦点提示内容"/></div>)}}// 2、渲染组件ReactDOM.render(<MyComponent/>, document.getElementById("example1"))
</script>
</body>
展示:
3.3.6 步骤、技术点
大体步骤与前一样
- 点击事件要在constructor构造器中进行bind()方法绑定。
- ref使用方法一:
ref属性
的value值为唯一值,然后在点击事件中 通过this.refs.ref属性名
获取 - ref使用方法二:
ref属性
的value值为回调函数{input => this.inputMsg = input}
,返回一个,然后在点击事件中 通过this.inputMsg
获取
六、组件的组合
6.1 需求描述
功能: 组件化实现此功能
- 显示所有todo列表
- 输入文本, 点击按钮显示到列表的首位, 并清除输入的文本
6.2 代码实例
<body>
<div id="example"></div>
<script type="text/javascript" src="../js/react.development.js"></script>
<script type="text/javascript" src="../js/react-dom.development.js"></script>
<script type="text/javascript" src="../js/prop-types.js"></script>
<script type="text/javascript" src="../js/babel.min.js"></script>
<script type="text/babel">/*** 界面中有一个文本框和按钮,按钮中显示下面的几个数据* 下面是一个 ul 列表,默认遍历 数组中的数据。* 事件:点击按钮,文本框中的数据出现在下面中的 ul 列表中*//***问题:数据保存在哪个组件内?* 看数据是某个组件需要(给它),还是某些组件需要(给共同的父组件)*问题2:需要在子组件中改变父组件的状态* 子组件不能直接改变父组件的状态* 状态在哪个组件,更新状态的行为(方法)就应该定义在哪个组件* 解决:父组件定义函数,传递给子组件,子组件调用**组件化编写功能的流程* 1、拆分组件* 2、实现静态组件(只有静态界面,没有动态数据和交互)* 3、实现动态组件* 1)实现初始化数据动态显示* 2) 实现交互功能*/// 主界面class Counter extends React.Component {constructor(props) {super(props)// 初始化状态this.state = {todos: ['吃饭', '睡觉', '打豆豆']}this.addTodos = this.addTodos.bind(this)}// 定义一个添加的函数addTodos(todo) {// this.state.todos.unshift(todo) //不能这么做const {todos} = this.statetodos.unshift(todo)// 更新状态this.setState({todos})}render() {const {todos} = this.statereturn (<div><h1>Simple TODO List</h1><Add count={todos.length} addTodos={this.addTodos}/><List todos={todos}/></div>)}}// 子界面class Add extends React.Component {constructor(prop) {super(prop)this.addData = this.addData.bind(this)}render() {return (<div><input type="text" ref={input => this.todoInput = input}/><button onClick={this.addData}>add # {this.props.count + 1} </button></div>)}addData() {// 1、读取输入的数据const data = this.todoInput.value.trim();// 2、检查合法性if (!data) {return}// 3、添加console.log(data)this.props.addTodos(data)// 4、清除输入this.todoInput.value = ''}}// 数据校验,放在上面出错Add.propTypes = {count: PropTypes.number.isRequired,addTodos: PropTypes.func.isRequired}// 子界面class List extends React.Component {render() {const {todos} = this.props;/* => : 箭头函数的意义,有两个:函数、return, 这里如果加 {}:方法体 的话,里面一定要有 return*//*todos.map((value, index)=><li key={index}>{value}</li>)*/return (<div><ul>{todos.map((value, index) => {return <li key={index}>{value}</li>})}</ul></div>)}}List.propTypes = {todos: PropTypes.array.isRequired}ReactDOM.render(<Counter/>, document.getElementById('example'))
</script>
</body>
6.3 技术点(注意:数据在哪,操作方法就在哪)
- 设计三个组件,一个主页面Counter、一个添加页面Add、一个列表页面List
- state数据在主页面中,todos数组会传给List组件,todos长度、添加的方法addTodos()会传给Add组件。
- 注意,方法也可以作为数据传给子组件。通过
this.props
进行接收。 - 在Add组件中调用父组件的添加方法。
- 在List组件中通过
this.props.todos
获取数据,然后在render()方法中进行遍历渲染出来。
6.4 React工具使用,查看三个属性
在Google中安装扩展软件,安装React扩展工具。可以查看自己定义的组件,以及三大属性,其实只能看到state和props,这两个是在组件上,ref是在标签上,这个只能在元素中查看。
看截图:
Counter类组件
Add类组件
6.5 功能界面的组件化编码流程(无比重要)
拆分组件: 拆分界面,抽取组件
实现静态组件: 使用组件实现静态页面效果
实现动态组件
a. 动态显示初始化数据
b. 交互功能(从绑定事件监听开始)
七、收集表单数据
7.1 需求描述
需求: 自定义包含表单的组件
- 输入用户名密码后, 点击登陆提示输入信息
- 不提交表单
7.2 理解
问题: 在react应用中, 如何收集表单输入数据
包含表单的组件分类
a. 受控组件: 表单项输入数据能自动收集成状态
b. 非受控组件: 需要时才手动读取表单输入框中的数据
7.3 代码实例
<body>
<div id="example"></div>
<script type="text/javascript" src="../js/react.development.js"></script>
<script type="text/javascript" src="../js/react-dom.development.js"></script>
<script type="text/javascript" src="../js/prop-types.js"></script>
<script type="text/javascript" src="../js/babel.min.js"></script>
<script type="text/babel">/*** 需求: 自定义包含表单的组件* 1、界面如下所示* 2、输入用户名密码后,点击登陆提示输入信息* 3、不提交表单 event.preventDefault()*/class LoginForm extends React.Component {constructor(prop) {super(prop)this.state = {pwd: ''}this.handleLogin = this.handleLogin.bind(this)this.handleChange = this.handleChange.bind(this)}render() {return (/*** 用户名 为非受控组件* 密码 为受控组件*/<form action="/test" onSubmit={this.handleLogin}>用户名:<input type="text" ref={input => this.username = input}/>密码: <input type="password" value={this.state.pwd} ref={input => this.password = input}onChange={this.handleChange}/><input type="submit" value="登陆"/></form>)}handleLogin(event) {const uname = this.username.value // 操作DOMconst {pwd} = this.state // 操作react 属性alert(`准备提交的用户名为${uname}, 密码${pwd}`)// 阻止事件的默认行为(提交)event.preventDefault()}handleChange(event) {// 读取输入框的值const password = event.target.value// 更新pwd的状态this.setState({pwd: password})}}ReactDOM.render(<LoginForm/>, document.getElementById('example'))
</script>
</body>
页面:
7.4 步骤、技术点
步骤与前一致
- 这里需要理解**受控组件和非受控组件**。
- 受控组件:通过onChange()事件,将input值与state的值链接起来,进行统一。
八、组件生命周期
8.1 需求效果
需求: 自定义组件
- 让指定的文本做显示/隐藏的渐变动画
- 切换持续时间为2S
- 点击按钮从界面中移除组件界面
8.2 理解
- 组件对象从创建到死亡它会经历特定的生命周期阶段
- React组件对象包含一系列的勾子函数(生命周期回调函数), 在生命周期特定时刻回调
- 我们在定义组件时, 可以重写特定的生命周期回调函数, 做特定的工作
8.3 生命周期流程图
8.4 生命周期详述
- 组件的三个生命周期状态:
- Mount:插入真实 DOM
- Update:被重新渲染
- Unmount:被移出真实 DOM
- React 为每个状态都提供了勾子(hook)函数
- componentWillMount()(舍弃)
- componentDidMount()
- componentWillUpdate()
- componentDidUpdate()
- componentWillUnmount()
- 生命周期流程:
a. 第一次初始化渲染显示: ReactDOM.render()- constructor(): 创建对象初始化state
- componentWillMount() : 将要插入回调
- render() : 用于插入虚拟DOM回调
- componentDidMount() : 已经插入回调
b. 每次更新state: this.setSate() - componentWillUpdate() : 将要更新回调
- render() : 更新(重新渲染)
- componentDidUpdate() : 已经更新回调
c. 移除组件: ReactDOM.unmountComponentAtNode(containerDom) - componentWillUnmount() : 组件将要被移除回调
8.5 重要的勾子
- render(): 初始化渲染或更新渲染调用
- componentDidMount(): 开启监听, 发送ajax请求
- componentWillUnmount(): 做一些收尾工作, 如: 清理定时器
- componentWillReceiveProps(): 后面需要时讲
九、虚拟DOM与DOM Diff算法
9.1 代码实例
class HelloWorld extends React.Component {constructor(props) {super(props)this.state = {date: new Date()}}componentDidMount () {setInterval(() => {this.setState({date: new Date()})}, 1000)}render () {console.log('render()')return (<p>Hello, <input type="text" placeholder="Your name here"/>! It is {this.state.date.toTimeString()}</p>)}
}ReactDOM.render(<HelloWorld/>,document.getElementById('example')
)
9.2 基本原理图
十、react引用(基于react脚手架)
10.1 使用create-react-app创建react应用
10.1.1 react脚手架
xxx脚手架: 用来帮助程序员快速创建一个基于xxx库的模板项目
a. 包含了所有需要的配置
b. 指定好了所有的依赖
c. 可以直接安装/编译/运行一个简单效果react提供了一个用于创建react项目的脚手架库:
create-react-app
项目的整体技术架构为:
react + webpack + es6 + eslint
使用脚手架开发的项目的特点:
模块化, 组件化, 工程化
10.1.2 创建项目并启动
npm install -g create-react-app
create-react-app hello-react
cd hello-react
npm start
10.1.3 react脚手架项目结构
ReactNews|--node_modules---第三方依赖模块文件夹|--public|-- index.html-----------------主页面|--scripts|-- build.js-------------------build打包引用配置|-- start.js-------------------start运行引用配置|--src------------源码文件夹|--components-----------------react组件|--index.js-------------------应用入口js|--.gitignore------git版本管制忽略的配置|--package.json----应用包配置文件 |--README.md-------应用描述说明的readme文件
10.2 项目结构
项目入口 js index.js
10.2 demo:评论管理
效果:
拆分组件:
应用组件: App
- state: comments/array
添加评论组件: CommentAdd - state: username/string, content/string
- props: add/func
评论列表组件: CommentList - props: comment/object, delete/func, index/number
评论项组件: CommentItem - props: comments/array, delete/func
实现静态组件
实现动态组件
- 动态展示初始化数据
- 初始化状态数据
- 传递属性数据
- 响应用户操作, 更新组件界面
- 绑定事件监听, 并处理
- 更新state
10.3 demo:评论管理
项目目录:
代码上库啦。
十一、react ajax
11.1 理解
11.1.1 前置说明
- React本身只关注于界面, 并不包含发送ajax请求的代码
- 前端应用需要通过ajax请求与后台进行交互(json数据)
- react应用中需要集成第三方ajax库(或自己封装)
11.1.2 常用的ajax请求库
jQuery: 比较重, 如果需要另外引入不建议使用
axios: 轻量级, 建议使用
a. 封装XmlHttpRequest对象的ajax
b. promise风格
c. 可以用在浏览器端和node服务器端fetch: 原生函数, 但老版本浏览器不支持
a. 不再使用XmlHttpRequest对象提交ajax请求
b. 为了兼容低版本的浏览器, 可以引入兼容库fetch.js
11.1.3 效果
需求:
- 界面效果如下
- 根据指定的关键字在github上搜索匹配的最受关注的库
- 显示库名, 点击链接查看库
- 测试接口: https://api.github.com/search/repositories?q=r&sort=stars
在这里插入图片描述
11.1.4 代码实例
<body>
<div id="example"></div>
<script type="text/javascript" src="../js/react.development.js"></script>
<script type="text/javascript" src="../js/react-dom.development.js"></script>
<script type="text/javascript" src="../js/prop-types.js"></script>
<script type="text/javascript" src="../js/babel.min.js"></script>
<script type="text/javascript" src="https://cdn.bootcss.com/axios/0.19.0-beta.1/axios.js"></script>
<script type="text/babel">/*** 需求:* 1、界面效果如下,* 2、根据指定的关键字在GitHub上搜索匹配的最受关注的库* 3、显示库名,点击链接查看库* 4、测试接口:https://api.github.com/search/repositories?q=r&sort=stars*/class MostStarRepo extends React.Component {state = {repoName: '',repoUrl: ''}// 最后发请求componentDidMount() {// 使用 axios 发送 异步的Ajax 请求 re:可以改变可以传 sort=stars:排序模式const url = 'https://api.github.com/search/repositories?q=re&sort=stars'axios.get(url).then(response => {const result = response.dataconsole.log(response);// 得到数据const {name, html_url} = result.items[0]// 更新状态this.setState({repoName: name,repoUrl: html_url})})// 错误信息.catch(error => {alert(error.message)})// 使用 fetch 发送异步的 Ajax 请求/*fetch(url).then(response => {return response.json()}).then(data => {// 得到数据const {name, html_url} = data.items[0]// 更新状态this.setState({repoName: name,repoUrl: html_url})})*/}render() {const {repoName, repoUrl} = this.stateif (!repoName) {return <h2>Loading</h2>} else {return <h2>Most star repo is <a href={repoUrl}>{repoName}</a></h2>}}}ReactDOM.render(<MostStarRepo/>, document.getElementById('example'))
</script>
</body>
11.2 axios
11.2.1 文档
https://github.com/axios/axios
11.2.1 相关API
- GET请求
axios.get('/user?ID=12345').then(function (response) {console.log(response);}).catch(function (error) {console.log(error);});axios.get('/user', {params: {ID: 12345}}).then(function (response) {console.log(response);}).catch(function (error) {console.log(error);});
- POST请求
axios.post('/user', {firstName: 'Fred',lastName: 'Flintstone'
})
.then(function (response) {console.log(response);
})
.catch(function (error) {console.log(error);
});
11.3 demo: github users
11.3.1 需求描述
11.3.2 拆分组件
App
- state: searchName/string
Search - props: setSearchName/func
List
- props: searchName/string
- state: firstView/bool, loading/bool, users/array, errMsg/string
11.3.3 代码实例
上库啦······ 库中代码为:13_react-app
- 编写静态组件
- 编写动态组件:
componentWillReceiveProps(nextProps)
: 监视接收到新的props, 发送ajax
使用axios库发送ajax请求
11.4 Fetch
11.4.1 文档
- https://github.github.io/fetch/
- https://segmentfault.com/a/1190000003810652
11.4.2 相关API
- GET请求
fetch(url).then(function(response) {return response.json()
}).then(function(data) {console.log(data)
}).catch(function(e) {console.log(e)
});
- POST请求
fetch(url, {method: "POST",body: JSON.stringify(data),
}).then(function(data) {console.log(data)
}).catch(function(e) {console.log(e)
})
十二、几个重要技术总结
12.1 组件间通信
12.1.1 方式一: 通过props传递
- 共同的数据放在父组件上, 特有的数据放在自己组件内部(state)
- 通过props可以传递一般数据和函数数据, 只能一层一层传递
- 一般数据–>父组件传递数据给子组件–>子组件读取数据
- 函数数据–>子组件传递数据给父组件–>子组件调用函数
12.1.2 方式二: 使用消息订阅(subscribe)-发布(publish)机制
- 工具库: PubSubJS
- 下载: npm install pubsub-js --save
- 使用:
import PubSub from ‘pubsub-js’ //引入
PubSub.subscribe(‘delete’, function(data){ }); //订阅
PubSub.publish(‘delete’, data) //发布消息
12.1.3 方式三: redux
后面专门讲解
12.2 事件监听理解
12.2.1 原生DOM事件
- 绑定事件监听
a. 事件名(类型): 只有有限的几个, 不能随便写
b. 回调函数 - 触发事件
a. 用户操作界面
b. 事件名(类型)
c. 数据()
12.2.2 自定义事件(消息机制)
- 绑定事件监听
a. 事件名(类型): 任意
b. 回调函数: 通过形参接收数据, 在函数体处理事件 - 触发事件(编码)
a. 事件名(类型): 与绑定的事件监听的事件名一致
b. 数据: 会自动传递给回调函数
12.3 ES6常用新语法
- 定义常量/变量: const/let
- 解构赋值: let {a, b} = this.props import {aa} from ‘xxx’
- 对象的简洁表达: {a, b}
- 箭头函数:
a. 常用场景
组件的自定义方法: xxx = () => {}
参数匿名函数
b. 优点:
简洁
没有自己的this,使用引用this查找的是外部this - 扩展(三点)运算符: 拆解对象(const MyProps = {}, <Xxx {…MyProps}>)
- 类: class/extends/constructor/super
- ES6模块化: export default | import
十三、react-router
13.1 项目理解
13.1.1 react-router的理解
- react的一个插件库
- 专门用来实现一个SPA应用
- 基于react的项目基本都会用到此库
13.1.2 SPA的理解
- 单页Web应用(single page web application,SPA)
- 整个应用只有一个完整的页面
- 点击页面中的链接不会刷新页面, 本身也不会向服务器发请求
- 当点击路由链接时, 只会做页面的局部更新
- 数据都需要通过ajax请求获取, 并在前端异步展现
13.1.3 路由的理解
什么是路由?
a. 一个路由就是一个映射关系(key:value)
b. key为路由路径, value可能是function/component路由分类
a. 后台路由: node服务器端路由, value是function, 用来处理客户端提交的请求并返回一个响应数据
b. 前台路由: 浏览器端路由, value是component, 当请求的是路由path时, 浏览器端前没有发送http请求, 但界面会更新显示对应的组件后台路由
a. 注册路由:router.get(path, function(req, res))
b. 当node接收到一个请求时, 根据请求路径找到匹配的路由, 调用路由中的函数来处理请求, 返回响应数据前端路由
a. 注册路由:< Route path="/about" component={About}>
b. 当浏览器的hash变为#about时, 当前路由组件就会变为About组件
13.1.4 前端路由的实现
history库
a. 网址: https://github.com/ReactTraining/history
b. 管理浏览器会话历史(history)的工具库
c. 包装的是原生BOM中window.history和window.location.hashhistory API
a. History.createBrowserHistory(): 得到封装window.history的管理对象
b. History.createHashHistory(): 得到封装window.location.hash的管理对象
c. history.push(): 添加一个新的历史记录
d. history.replace(): 用一个新的历史记录替换当前的记录
e. history.goBack(): 回退到上一个历史记录
f. history.goForword(): 前进到下一个历史记录
g. history.listen(function(location){}): 监视历史记录的变化
13.2 react-router相关API
13.2.1 react-router组件
<BrowserRouter>
<HashRouter>
<Route>
<Redirect>
<Link>
<NavLink>
<Switch>
13.2.2 其它
- history对象
- match对象
- withRouter函数
13.3 基本路由使用
13.3.1 效果
13.3.2 准备
- 下载
react-router
:npm install --save react-router@4
- 引入
bootstrap.css
:<link rel="stylesheet" href="/css/bootstrap.css">
13.4 嵌套路由使用
13.4.1 效果
13.5 向路由组件传递参数数据
13.5.1 效果
13.6 多种路由跳转方式(重要)
- 一种为标签方式跳转
- 一种为事件方式跳转:添加事件,需要借助history对象
原来没加router时,组件的属性有 props、state
加上route时,在Route下的组件上,有了history、location、match三个对象。
13.6.1 效果
13.6.2 代码实例
都上库啦。
代码为 14_react_router,三级路由都在这一个项目中。
十四、React UI
14.1 最流行的开源React UI组件库
14.1.1 material-ui(国外)
官网: http://www.material-ui.com/#/
github: https://github.com/callemall/material-ui
14.1.2 ant-design(国内蚂蚁金服)
PC官网: https://ant.design/index-cn
- 移动官网: https://mobile.ant.design/index-cn
Github: https://github.com/ant-design/ant-design/
- Github: https://github.com/ant-design/ant-design-mobile/
14.2 ant-design-mobile使用入门
14.2.1 效果
14.2.2 使用create-react-app创建react应用
npm install create-react-app -g
create-react-app antm-demo
cd antm-demo
npm start
14.2.3 搭建antd-mobile的基本开发环境
下载
npm install antd-mobile --save
- src/App.jsx
import React, {Component} from 'react'
// 分别引入需要使用的组件
import Button from 'antd-mobile/lib/button'
import Toast from 'antd-mobile/lib/toast'export default class App extends Component {handleClick = () => {Toast.info('提交成功', 2)}render() {return (<div><Button type="primary" onClick={this.handleClick}>提交</Button></div>)}
}
src/index.js
import React from 'react';
import ReactDOM from 'react-dom'
import App from "./App"
// 引入整体css
import 'antd-mobile/dist/antd-mobile.css'ReactDOM.render(<App />, document.getElementById('root'))
index.html
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no" /><script src="https://as.alipayobjects.com/g/component/fastclick/1.0.6/fastclick.js"></script>
<script>if ('addEventListener' in document) {document.addEventListener('DOMContentLoaded', function() {FastClick.attach(document.body);}, false);}if(!window.Promise) {document.writeln('<script src="https://as.alipayobjects.com/g/component/es6-promise/3.2.2/es6-promise.min.js"'+'>'+'<'+'/'+'script>');}
</script>
7.2.4. 实现按需打包(组件js/css)
下载依赖包
yarn add react-app-rewired customize-cra babel-plugin-import --save
修改默认配置:
package.json
"scripts": {"start": "react-app-rewired start","build": "react-app-rewired build","test": "react-app-rewired test --env=jsdom"
}
- config-overrides.js
const {injectBabelPlugin} = require('react-app-rewired');
module.exports = function override(config, env) {config = injectBabelPlugin(['import', {libraryName: 'antd-mobile', style: 'css'}], config);return config;
};
- 编码
// import 'antd-mobile/dist/antd-mobile.css'// import Button from 'antd-mobile/lib/button'
// import Toast from 'antd-mobile/lib/toast'
import {Button, Toast} from 'antd-mobile'
扩展,数组方法
1. map()
遍历数组
/**
* 功能:动态展示列表数据
*
* 问题:如何将一个数据的数组 转换为 一个标签的数组 很常用
* 使用数组的map() 方法 和 箭头函数
* */
const names = ['jQuery', 'zepto', 'angular', 'react', 'vue']// 1、创建虚拟DOM// li 标签一定要带 key属性,而且还不能一样 否则警告const ul = (<ul>{names.map(name=> <li key={name}>{name}</li>)}</ul>)
2. unshift()
在数组的头部添加新值
3. splice()
splice(value, 1):删除
splice(value, 0, value2):替换
splice(value): 添加
4. filter()
过滤数组,将下标不等于0的过滤掉,返回一个新的数组。
const comments = [{username: 'Tom', content: 'React 挺好的!'},{username: 'Jack', content: 'React 挺简单的!'}
];state.filter((comment, index) => {return (index !== 0)
});
react学习笔记一:入门级小白到脚手架(create-react-app)开发项目相关推荐
- react学习笔记(二)编写第一个react组件
继续上一节课的内容,打开App.js:会看到如下代码: import React, { Component } from 'react'; //在此文件中引用React,以及reat的组件类 impo ...
- 学习笔记(2):uni-app实战社区交友类app开发-引入css动画库
立即学习:https://edu.csdn.net/course/play/28009/381722?utm_source=blogtoedu 1. 百度搜索并打开 animate.css . ...
- 学习笔记(1):uni-app实战社区交友类app开发-引入自定义图标库
立即学习:https://edu.csdn.net/course/play/28009/381721?utm_source=blogtoedu 1. 在iconfont.cn图标库中打包下载图标文件压 ...
- react学习笔记1--基础知识
什么是react A JAVASCRIPT LIBRARY FOR BUILDING USER INTERFACES[React是一个用于构建用户界面的JavaScript库.] React之所以快, ...
- react render没更新_web前端教程分享React学习笔记(一)
web前端教程分享React学习笔记(一),React的起源和发展:React 起源于 Facebook 的内部项目,因为该公司对市场上所有 JavaScript MVC 框架,都不满意,就决定自己写 ...
- react组件卸载调用的方法_好程序员web前端培训分享React学习笔记(三)
好程序员web前端培训分享React学习笔记(三),组件的生命周期 React中组件也有生命周期,也就是说也有很多钩子函数供我们使用, 组件的生命周期,我们会分为四个阶段,初始化.运行中.销毁.错误处 ...
- React学习笔记:入门案例
React学习笔记:入门案例 React 起源于 Facebook 内部项目,因为市场上所有 JavaScript MVC 框架都不令人满意,公司就决定自己写一套,用来架设 Instagram 的网站 ...
- React学习笔记(五) 状态提升
状态提升究竟是什么东西呢?别急,下面让我们一步一步来看看究竟要怎么使用状态提升 假设我们有这样一个需求,提供两个输入框(分别属于两个组件),保证输入框里面的内容同步 好,下面我们先来封装一个输入框组件 ...
- React学习笔记 - 组件Props
React Learn Note 4 React学习笔记(四) 标签(空格分隔): React JavaScript 三.组件&Props 组件可以将UI切分成一些独立的.可复用的部件,这样你 ...
最新文章
- matlab计算方程fsolve,matlab中关于fsolve解非线性方程组的问题
- 【企业管理】摆脱三个依赖
- python3精要(51)--抛出异常与自定义异常
- R语言观察日志(part4)--paste函数
- file协议访问linux,Mozilla Firefox for Android 'file'协议未授权访问漏洞(CVE-2014-1501)
- int转unsigned int_谢劲课题组在基于锰催化的转金属化基元反应取得系列进展
- 分库分表全面了解分析
- JVM学习-类文件结构
- dc综合与pt静态时序分析(中文)_新能源汽车小三电系统(PDU/DC/OBC)技术研究详解...
- [转载]Yahoo!的分布式数据平台PNUTS简介及感悟
- java submit execute_ExecutorService中submit和execute的区别
- matlab GUI页面 科学计算器代码
- 操作系统——进程间通信
- pdf照片显示正常打印时被翻转_【20考研】现场确认完没事了?!准考证打印别大意!...
- word2010计算机实验报告,Word2010计算机实验报告--
- 电阻式温度计 - 铂电阻温度计 - PT100
- 体绘制加速技术之数据异步传输
- 计算机显示器不亮灯,电脑液晶显示器指示灯不亮是为什么?
- adams功能区不显示_基于ADAMS对初始角和相位角修改模拟力矩波动
- ASP.NET统计在线人数
热门文章
- RH850从0搭建Autosar开发环境【1】- 如何创建Davinci Configurator配置工程
- Pyecharts数据可视化之折线图(阶梯图、平滑曲线图、面积图)、K线图、常用配置项
- 编译原理——语法分析器(C/C++代码实现)
- Mac OS 10.15 修改登录壁纸
- 使用three.js + geojson 完成广西地图的绘制(上篇)
- 【低功耗蓝牙】② 蓝牙状态切换和事件处理
- Hive 数据倾斜问题定位排查及解决(实际案例)
- mysql查询总成绩高于240_Egret应用开发实践(02) MVC 模块化 - SegmentFault 思否
- 一个简单的SQL注入攻击
- opencv图像对齐与图像相减python