两大优点:虚拟dom的操作,数据流向的控制。
核心思想:把用户界面抽象成一个个组件。
通过引入jsx语法,复用组件,同时保证组件结构清晰。
react 特点:
- 声明式设计 --采用声明范式,可以轻松描述应用(自动dom操作)
- 高效 --通过虚拟DOM,最大限度的减少与DOM的交互
- 灵活 --react可以与已知的库或框架很好的配合
- JSX --JSX是JavaScript语法的扩展
- 组件 --通过构建组件,使代码更容易得到复用
- 单向响应的数据流 --减少了重复代码
核心:组件
组件的设计目的:
- 提高代码复用率(组件封装)
- 降低测试难度(高内聚低耦合)和代码复杂度(直观的语法)
专注视图层,虚拟dom,函数式编程(精髓)。
函数式编程的好处:
- 代码简洁,开发快速
- 接近自然语言,易于理解
- 更方便的代码管理
- 易于“并发编程”
- 代码的热升级
1、在return里面,只能有一个根节点,注释规则{/注释/} react解析 {} 单括号
2、JSX基本语法 编译过程由Babel 的 JSX 编译器实现。
XML基本语法:定义标签时,只允许被一个标签包裹,标签一定要闭合。
元素类型:小写首字母对应DOM元素,大写首字母对应组件元素
3、多个组件调用 <App/ >
4、react中如何去写css
- 基于class 低版本15版设置类名要写成className ,高版本16中class和className都能生效
- 基于inner css(行间样式 只能解析JSON格式)例如: style={{color:“blue”}} (facebook主张的方式)
- 原型链和全局变量
var sty = {color:'purple'} //全局变量
<div style={sty}>全局变量</div>
App.prototype.stys={ color:'yellow' }
<div style={this.stys}>原型</div>
- react中的事件机制:
点击onClick 触摸结束:onTouchEnd
<button onClick={tap}>事件1</button>
修正this
15 版
<button onClick={this.tap3.bind(this,'hello')}>事件3</button> //箭头函数
<button onClick={()=>this.tap4(321)}>事件4</button> //bind绑定
16 版— 对其类对象来说,如果函数内部的this需要指向函数本身,必须进行this指针的修正,否则就是undefined,
//箭头函数 //bind绑定
constructor(props){
super(props)
this.tap = this.tap.bind(this)
}
<button onClick={this.tap}>事件</button>
方法:箭头函数、bind、constructor构造器
注意:15版有逗号,16版不需要,因为16版每个函数是独立的
- HTML转义
var content='<strong>content</strong>';
React.render(
<div dangerouslySetInnerHTML={{__html: content}}></div>,
document.body
);
引入的外部脚本:
react.min.js包含创建组件的核心api以及diff算法
react-dom.min.js负责将虚拟dom/组件渲染成真实dom
browser.min.js 翻译器,将babel/jsx语法翻译成纯js语言
type=“text/babel”
渲染 ReactDOM.render(,document.getElementById(‘app’))
15版和16版的不同:
- —创建
15版--- var App = React.createClass({render(){return(<div></div>)}})
16版--- class App extends React.Component{ render(){ return( <div> </div> ) } }
- —定义:15版可以使用16的定义,但16版已经完全废除了React.createClass的方法
- —关于使用class定义,低版本15版里要使用className,高版本16 两者都可以
- —高低版的本质区别:低版函数内部的this默认指向组件本身,高版函数内部的this默认不指向本身,必须修正this
- —高版本废弃了mixins
属性和状态是react中数据传递的载体
属性
属性在react中一旦定义,不可修改,所以一般用来保存常量
属性传递的方式:
1、key:value 的形式
ReactDOM.render(,document.getElementById(‘app’))
2、展开式传值 只适合传对象形式
ReactDOM.render(<App {...obj}/>,document.getElementById('app'))
3、默认属性 (私有) 高版本里弃用
getDefaultProps(){
return{
str:'hello',
arr:[1,2],
obj:{ name:'小明', age:18 }
}
},
4、高版本特有
组件.defaultProps
App.defaultProps={
str:'hi',
arr:[8,9,7,6],
obj:{ name:'asdf', obj:18 }
}
构造器 不允许直接给props赋值
constructor(props){
super(props)
this.props.name={str:'hi',arr:[8,9,7,6]}
this.props.obj={
obj:{
name:'asdf',
obj:{name:'asdf',age:18}
}}
}
状态 state
一、定义:
低版本 钩子函数,高版本16已经废弃
getInitialState(){ return{ str:'状态' } } //低版本 高版本已废弃
高版本 在构造器中:
this.state={ str:'16状态' }
二、属性不同,但是状态可改变 setState一旦调用会导致render二次触发,所以禁止在render直接调用setState
this.state={ str:'16状态' }
<button onClick={this.tap3}>事件3 setState</button>
tap3() { this.setState({str:'状态以改变'}) }
react-webpack
配置webpack环境
npm i webpack webpack-cli webpack-dev-server css-loader style-loader react react-dom html-webpack-plugin babel-loader@7 babel-core babel-preset-es2015 babel-preset-react --save-dev
打包命令 webpack
webpack.config.js 基本配置
var path = require('path');
module.exports = {
mode: 'development',
entry: './main.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: '[name].min.js'
}
};
//production 生产
cssloader
module: {
rules: [
{
test: /\.css$/i,
use: ['style-loader', 'css-loader'],
},
],
},
devServer 热更新
devServer: {
contentBase: path.join(__dirname, 'dist'),
compress: true,
port: 9000
},
运行指令 webpack-dev-server
html-webpack-plugin 拷贝生成html文件,dist版本
var webpack = require('webpack');
var HtmlWebpackPlugin = require('html-webpack-plugin');
plugins: [
new HtmlWebpackPlugin({ template: './index.html' }),
new webpack.HotModuleReplacementPlugin()
]
babel-loader
npm install -D babel-loader @babel/core @babel/preset-env webpack
module: {
rules: [
{
test: /\.m?js$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: 'babel-loader',
query: {
presets: ['es2015','react']
}
}
}
]
}
接收对象的方法 import React,{Component} from ‘react’ 可以直接使用Component方法
Hook 16.8新增
可以在组件内创建局部状态,以及模拟生命周期函数核心对象 useState、useEffect
import React,{useState,useEffect} from 'react
useState可以在function定义的组件中设置一个局部状态,返回两个值
第一个是状态的名字,第二个为改变状态的方法
const [count,setCount] = useState(0)
展示:<p>{count}</p>
useEffect可以在function定义的组件中模拟组件生命周期函数,两个参数
第一个是回调函数,第二个执行回调函数的触发条件(array),空表示只执行一次(无代表多次)
useEffect(()=>{
console.log('only one)
},[])
受控组件和非受控组件 类组件
非受控组件 例如:<input type="text" value={this.state.value} />
改成受控组件
可以使用defaultValue
或者添加onChange={(e)=>this.change(e)}
然后设置 change(e){ this.setState({ value:e.target.value })
数据流
数据从父组件流向子组件
ref=“parentvalue” ref设置属性获取dom元素
this.refs.parentvalue.value this.refs.ref获取并存到state中
name={this.state.value} 给子组件设置key值
在子组件使用 this.props.name
从子组件流向父组件
1、在父组件中给调用的子组件设置key值
val={function(msg){
_this.setState({childvalue:msg})
}}
2、在子组件中获取要传的值
逻辑://this.props.val == function
//this.props.val(xxx) == function(a)
//this.refs.childvalue.value==msg
this.props.val(this.refs.childvalue.value)
React生命周期
生命周期指的是组件从初始化开始到结束的过程,或者是描述react组件从开始到结束的过程。
react对组件是通过生命周期给予的钩子函数进行管理的。
每个react组件都具有生命周期。
钩子函数:指的是系统某些状态和参数发生改变的时候,系统立马去通知对应处理的函数,叫钩子函数
总体阶段:mounted-------update------umount
- mounted—加载阶段/初始化阶段,将组件的jsx语法转为真实dom
- getDefaultProps 取得默认属性 (高版废弃)
- getInitialState 初始化状态 (高版废弃)
- componentWillMount 即将进入dom
- render 描绘dom
- componentDidMount 已经进入dom
- update-----组件运行中阶段,数据更新过程,只有当组件修改自身状态,或者父组件修改子组件属性的时候发生的阶段
- 组件将要接受新值componentWillReceiveProps(已加载组件收到新的参数时调用) 有参数时,参数指代的是当前最新接收的属性对象
- 组件是否更新 shouldComponentUpdate (影响整个项目的性能,决定视图的更新) 允许更新return true 可以把参数当作判断条件决定是否更新
- 组件即将更新 componentWillUpdate
- 必不可少的render
- 组件更新完毕时运行的函数 componentDidUpdate
- umount-------组件卸载阶段,组件被浏览器回收的阶段
卸载组件:ReactDOM.unmountComponentAtNode(‘节点’)
Diff算法 提升性能,解决性能浪费的问题
react中由当前状态决定UI界面,前后两个状态对应两套页面
然后由react来比较两个界面的区别,这时候需要对DOM树进行Diff算法分析。
- 层级数的查找,复杂度的问题,diff可以把复杂度降为一层
- 列表比较 ,通过加唯一的key值来方便查找
- 组件Components的比较 ,因为组件唯一,React只会匹配相同的类型的component
- 合并操作 ,当调用component的setState方法的时候,React将其标记为dirty,每个事件循环结束,检查所有标记进行 一次渲染组件
- 选择性子树渲染 shouldComponentUpdate()
数据加载
列表渲染,todolist
第一种方式:数组html模板
{
this.state.list.map((item,i)=>{
return <p>{i}-----{item}</p>
})
}
第二种方式:直接在jsx语法里返回相应的列表结构
var jsx=[] //存放html/jsx结构
this.state.list.map((item)=>{
jsx.push(<p>{item}</p>)
})
return调用: {jsx}
mixins函数(es6弃用)
vue中用来混入,实例化或组件内都可以混入外部的对象(data和methods混入后组件本身的优先级更高,亲生的高于外来的,而钩子函数–外来的先于本身的执行)
<button onClick={()=>obj.fn1()}>函数</button>
mixins:[obj] //混入外来的obj
<button onClick={()=>this.fn2()}>函数</button> {/*想用this替换obj需要使用mixins*/}