react
一.虚拟dom
dom : 浏览器中,提供的概念,用js对象,表示页面上的元素,并提供了操作元素的api
虚拟dom: 是框架中的概念; 它是开发框架的程序员,手动用js对象来模拟dom元素和嵌套关系;
- 本质: 用js对象,来模拟dom元素和嵌套关系
- 目的: 就是为了实现页面元素的高效更新
二.diff算法
-
tree diff : 新旧两棵dom树,逐层对比的过程,就是tree diff; 当整颗dom逐层对比完毕,则所有需要被按需更新的元素,必然能够找到
-
component diff : 在进行tree diff 的时候,每一层中,组件级别的对比,叫做 component diff
- 若对比前后,组件的类型相同 ,则暂时认为此组件不需要被更新
- 若对比前后,组件的类型不相同,则移除旧组件,创建新组件,并追加到页面上
-
element diff : 在进行组件对比的时候,如果两个组件类型相同 ,则需要进行元素级别的对比
三.react 创建项目
1.全局安装 yarn add react-create-app -g
2.创建一个项目 react-create-app [项目名称project name]
3.启动react服务 yarn start
。
yarn start 启动服务
yarn bulid 打包文件
yarn test 测试
yarn eject 显示相关的配置文件
react是基于webpack创建项目,react-create-app命令已帮我们配置好了相关配置,我们只需要操作react即可
四.jsx
在react中为了减少dom操作,使用js+xml形式书写代码
但这里的xml标签比真正的xml要严格多,标签必须要有闭合
// 1.导入包
import React from 'react';
import ReactDOM from 'react-dom';
// 2.创建虚拟dom
// var div2 = React.createElement('p',null,'这是一个p标签')
// var div1 = React.createElement('div',null,'这是根标签',div2)
// 以上写法太麻烦,所以react提供了jsx语法 ,
// jsx语法通过bobal转成上面createelement样式,再渲染给页面
let str = '这是一段内容';
let text = '这是一段文件'
let val = true;
let und = undefined;
let arr = ['这是第一个h1','这是第二个h1']
let content = <div>
{str}
<hr/>
{text}
<hr/>
{val ? true.toString() : false.toString()}
<hr/>
{und}
<hr/>
{null}
{arr.map((item,index)=>{
return <p key={index}>{item}</p>
})}
</div>
// 3.把创建的虚拟dom放到页面上
// ReactDOM.render(div1,window.root)
ReactDOM.render(content,window.root)
五.组件
函数式组件写法
这是Hollow.jsx页面中的中代码
import React from 'react';
// export default 向外暴露一个组件
export default function Hollow(props) {
return <div>
<p>{props.data.name}</p>
<p>{props.data.age}</p>
<p>{props.data.title}</p>
</div>
}
把写好的组件导入到下面这个index.js页面,然后由下面的页面渲染到页面上
// 创建组件 虚拟dom元素, 生命周期
import React from 'react';
// 把创建好的组件 和 虚拟dom 放到页面上展示
import ReactDOM from 'react-dom';
// 这里导入的jsx文件必须写后缀名,不然报错.除非有相关的配置,可以不写
import Hollow from '../component/1.hollow.jsx'
let obj = {
name: '的口吻',
age: '25',
title: '这是一个对象'
}
ReactDOM.render(<Hollow data={{ ...obj }}></Hollow>, window.root)
继承性组件写法class
首先了解一下类继承
1.在 class 的 { } 区间内,只能写 构造器、静态方法和静态属性、实例方法
2.class 关键字内部,还是用 原来的配方实现的;所以说,我们把 class 关键字,称作 语法糖;
3.class 中都有一个构造器,如果我们程序员没有手动指定构造器,那么,可以认为类内部有个隐形的、看不见的 空构造器,类似于 constructor(){}
4.构造器的作用,就是,每当 new 这个类的时候,必然会优先执行 构造器中的代码
class Person{
constructor(name,age){
// constructor放的是实例共有的私有属性
this.name = name;
this.age = age;
}
// 在这里面直接写的方法是实例的共有的方法
say(){
console.log('这是一个实例公有的方法')
}
// static 静态属性 放的是person这个类私有的属性与方法
static a = 10;
static Hi(){
console.log('这是这个类私有的方法,外界不可调用 ')
}
}
// extends继承
class A extends Person{
constructor(name,age){
// super 是一个函数,而且,它是 父类的 构造器;子类中的 super,其实就是父类中,constructor 构造器的一个引用;
// 构造器继承父亲的方法与属性,首先调用super方法,才有this
// super必须写在this之前
super(name,age);// 不写super会报错
console.log(this.name,this.age)
}
}
// new 一个实例对象
var a1 = new Person('的口吻',25)
a1.say()
var a2 = new A('大中企业',254)
a2.say()
class类组件的写法
// 创建组件 虚拟dom元素, 生命周期
import React,{Component} from 'react';
// 把创建好的组件 和 虚拟dom 放到页面上展示
import ReactDOM from 'react-dom';
class Hollow extends React.Component{
constructor(props){
super(props);// props只可读
this.state={// state可读可写,相当vue中的data
name:'李四',
age:this.props.data.age
}
}
// render 函数的作用,是 渲染 当前组件所对应的 虚拟DOM元素
render(){
return <div>
{this.props.data.name}
{this.state.name}
{this.state.age}
</div>
}
}
var lis = {
name:'张三',
age:30,
sex:'men'
}
ReactDOM.render(<Hollow data={{...lis}} />,window.root)
通过构造函数创建的组件是无状态组件,只有props,只可读,不可写
通过class创建的组件是有状态组件,有props , state 可读,可写
一般情况下,不需要通过外界传递数据过来,使用无状态组件
需要通过ajax传递数据用有状态组件,可以读写
六. 父子组件传值,事件
点击子组件的按钮改变父组件的字体背景颜色
// 1.导入包
import React from 'react'; // 创建组件 虚拟dom元素, 生命周期
import ReactDOM from 'react-dom'; // 把创建好的组件 和 虚拟dom 放到页面上展示
import "bootstrap/dist/css/bootstrap.css"
// 2.创建虚拟dom 父组件
class Panel extends React.Component {
constructor() {
super();
this.state = {color:'success'}
}
change=(color)=>{
this.setState({color:color})
}
render() {
return <div className='container'>
<div className='row'>
<div className={`panel panel-${this.state.color}`}>
<div className='panel-heading'>
<Header data={this.props.title} chan={this.change}/>
</div>
<div className='panel-body'></div>
</div>
</div>
</div>
}
}
// 子组件
class Header extends React.Component {
constructor() {
super();
}
chage=()=>{
this.props.chan("warning")
}
render() {
return <div>
<h1>{this.props.data}</h1>
// method1
{/* <button onClick={this.chage}>点击</button> */}
// method2
{<button onClick={this.props.chan.bind(null,"warning")}>点击</button>}
</div>
}
}
// 3.把dom渲染到页面上
ReactDOM.render(<Panel title="标题"></Panel>, window.root)
校验属性
import React from 'react';
import ReactDOM from 'react-dom';
import PropTypes from 'prop-types';
class Title extends React.Component{
constructor(){
super()
}
// 要求num必须是一个数字类型的;
// 抛出一个警告,但页面会渲染;
static PropTypes={
n:PropTypes.number
}
// 默认属性;
//如果属性被传行间属性传递进来,那么会默认获取当前的属性;如果行间传递,那么会走行间属性;
static defaultProps = {
n:"10"
}
render(){
return <div>{this.props.n}</div>
}
}
ReactDOM.render(<Title/>,document.getElementById('root'))
受控组件
受控组件可模仿vue的双向数据绑定
受控组件一般是一些form表单元素,
受控组件的值不可更改
必须添加onchange事件
class Box extends React.Component{
constructor(){
super();
this.state={
str:"请输入用户名",
str1:"请输入内容"
}
}
change=(key,e)=>{//事件
console.log(e,e.target)
this.setState({[key]:e.target.value})
}
render(){
return <div>
<input type="text" value={this.state.str} onChange={(e)=>this.change("str",e)}/>
<input type="text" value={this.state.str1} onChange={(e)=>this.change("str1",e)}/>
</div>
}
}
非受控组件
class Sum extends React.Component {
constructor() {
super();
this.state = { total: 0 }
}
change = () => {
console.log(this.refs)
// var total = Number(this.refs.a.value)+Number(this.refs.b.value)
var total = Number(this.refs.a.value) + Number(this.b.value)
this.setState({ total })
}
render() {
return <div onChange={this.change}>
<input ref="a" />+
{/*x代表的真实的dom,把元素挂载在了当前实例上*/}
<input ref={(x) => { this.b = x }} />=
{this.state.total}
</div>
}
}
react 生命周期
-
生命周期的概念:每个组件的实例,从 创建、到运行、直到销毁,在这个过程中,会出发一些列 事件,这些事件就叫做组件的生命周期函数;
-
React组件生命周期分为三部分:
- 组件创建阶段:特点:一辈子只执行一次
componentWillMount:
render:
componentDidMount:- 组件运行阶段:按需,根据 props 属性 或 state 状态的改变,有选择性的 执行 0 到多次
componentWillReceiveProps: 接收
shouldComponentUpdate:
componentWillUpdate:
render:
componentDidUpdate:- 组件销毁阶段:一辈子只执行一次
componentWillUnmount:
转载:https://www.race604.com/react-native-component-lifecycle/