reactive

作者: cj小牛 | 来源:发表于2019-09-30 10:52 被阅读0次

虚拟dom节点

通过javaScript 来虚拟dom 。通过虚拟的dom 来找到那些需要局部跟新的东西,这样可以提高程序的性能

Diff 算法

新旧Dom数,逐层对比的方式就叫做tree diff,每当我们从前到后,把所有层的节点对完成后,必然能够找到那些需要被更新的元素。

  • component diff;在对比每一层的时候,组件之间的对比,叫做component diff
    ;当对比组件的时候,如果两个组件的类型相同,则暂时认为这个组件不需要被更新,如果组件类型不同,则立即将就组建移除,新建一个组件,替换到被移除的位置。
  • element diff:在组件中每个元素也需要对比,那么元素的对比,叫做element diff
  • key: key 这个属性可以把页面上的Dom节点和虚拟DOM中的对象,做一层联系关系。

安装环境

  1. npm i react react-dom -s

  2. 在main.js 中导入

    import React from 'rect'
    import ReactDOM from 'rect-dom'
    
  3. 创建元素的方法
    react.creatElement() reac 创建一个自己的dom 元素

    reactDom.render('要渲染的虚拟Dom元素','要渲染到页面中的那个位置’)

     // react.creatElement()方法接受3个c参数
     // 参数1 。是个字符兑换类型的参数,表示要创建的元素类型
     // 参数2. 是一个属性,表示创建的这个元素上,有哪些属性。
     // 参数3. 从第三个参数开始,后面可放好多的虚拟Dom对象,这些参数表示子节点
     var mydiv = React.createElement('div',{title:'this is a div',id:'mydiv'},'这是一个div');


   渲染到页面
    ReactDOM.render(mydiv,document.getElementById('app'));

jsx 语法

像上main那样来创建Dom 很麻烦,维护框架的人给大家开发了jsx 语法。

    var mydiv= <div>这是一个div1111</div>
     ReactDOM.render(mydiv,document.getElementById('app'));

jsx :官网 https://react-1251415695.cos-website.ap-chengdu.myqcloud.com/docs/introducing-jsx.html

但是 又识别不了JSX语法,所以要安装转换工具

  npm i babel-preset-react -D

然后在 .babelrc 文件中 "presets": ["env","stage-0","react"],
这样就可以识别到了。这样就可以向写html 那样来实现react了

  • 如果要在jsx语法内部,书写JS代码,那么,所有的JS代码,必须写在{}内部。
  • 如果当编译器,在编译JSX中遇到'<'那么就把它当做HTML 代码去编译,如果遇到{} 就把括号内的代码当做普通JS代码去执行。
  • 在{} 中可以写任何符合js规范的代码
  • 在jsx 中要为元素添加Class 属性,那么必须要写成 className 因为 class 在Es6中是关键字。和‘class’类似,label 的for熟悉要写成htmFor
  • 在JSX创建DOM节点只能有一个跟元素进行包裹
  • 注释要写在括号中{/这是注释/}

reactive中的组件

    // 在react 中构建函数就是组件

// 可以把构造函数的名称,当做组件的名称,以HTML 形式引入页面中既可 组件名必须大写
function Hello(){

return <div>fdsfasfkskfsfjasjfj</div> 

}
ReactDOM.render(<div><Hello></Hello> </div>,document.getElementById('app'));

怎么给组件传值
1.
 function Hello(){

  return <div>fdsfasfkskfsfjasjfj {name}</div>

}
 var name='zc'
 var age = 100
  ReactDOM.render(<div><Hello name={name} age={age}></Hello> </div>,document.getElementById('app'));
  1. 给组件传对象
    function Hello(Persion){
    //. 传过来的是一个对象,这个对象里面的值是readonly。值改不来了
    return <div>{Persion.name}</div>
    // 取值得方式
    }
    var Persion = {
    name:'zs',
    age:15,
    }
    // 给组件传值 用的是对象展开
    ReactDOM.render(<div><Hello {...Persion}>
    </Hello> </div>,document.getElementById('app'));

将js文件改成jsx

  1. 在js中写的jsx 语法(html) 文件中无法自动提示,需要把.js文件改成 .jsx 语法。
  2. 在web pack.config.js 文件中把rules {test:/.(js|jsx)$/,use:'babel-loader',exclude:/node_modules/},
    这样就可以了。

class

    //class 里面只能写属性和方法。
class per {
// class 里面有一个构造器
constructor(name,age){
    this.age = age;
    this.name = name;
}
sayHello(){
   console.log('hello')
}
}

var p  =  new per("name",30);

console.log(p.sayHello());
  1. 通过继承的方式,把class 变成组件

class Hello2 extends React.Component{
constructor(props){
super(props);
this.state ={
msg:'这是hello1组件的私有数据',
info:'第二个数据'
}

}
    render(){
        return <div>防守打法克鲁赛德荆防颗粒 
  // 这里参数传递,只要是props 中的参数都是只读的
  <p> {this.props.name}</p></div>
    }

}

ReactDOM.render(<div><Hello {...Persion}></Hello> <Hello2 name="haha"></Hello2></div>,document.getElementById('app'));

function 创建的组件和class 组件的区别

  1. 使用function 构造函数创建的组件,内部没有state 私有数据,只有一个props来接收外界船体过阿里的数据。
  2. 使用class 创建的组件,内部,除了有this.props这个只读属性之外,还有一个专门用于窜访自己数据的this.state属性。这个state 是可读写的。
  3. 基与上面的区别:我们可以为这两种创建组件的方式,下定义了:使用function创建的组件,叫做【无状态组件】用class 创建的组件叫做【有状态组件】
    4 . 有状态组件和无状态组件,最本质的区别,就是有无state属性,同时,class 创建的组件,有自己的生命周期函数,但是,funciton创建的组件没有自己的生命周期函数;

什么时候使用有状态组件?

1.如果一个组件需要存放自己的私有数据,或者需要爱组件的不同阶段执行不同的业务逻辑,要使用有状态组件。

  1. 如果一个组件,只需要根据外界船体过来的props,渲染固定的页面结构就万事了,此时,非常适合使用无状态组件

style样式模块化

  1. 在webpack.config.js 中为CSS-loader 启用模块化
    {test:/.css$/,user:['style-loader','css-loader?modules&loaclIdentName=[name]_[local]-[hash:5]'}
  2. 使用:gloabal()定义全局样式

组件的生命周期

  • 组件生命周期为三部分
    • 组件创建阶段:组件创建阶段的生命周期函数,有一个显著的特点:创建阶段的生命周期函数,在组件的一辈纸中只执行一次

componentWillMount:组件将要被挂载,此时还没有开始渲染dom
render:第一次渲染真正的DOM,当render执行完,内存中就有了完整的虚拟DOM
componentDidMount:组件完成了挂载,此时组件已经在页面上了。当这个方法执行完,组件就进入了运行状态。

  • 组件运行阶段 也有一个显著的特点:根据state 和props 的该不安,有选择性的处罚0次或者多次;

conponentWillReceiveProps :组件将要接收新属性,此时只要这个方法被触发,就证明父组件为当前子组件传递了新的值。
shouldComponentUpdate :组件是否需要被更新,此时,组件尚未被更新,但是,state和props 肯定是最新的。
componentWillUpdate:组件将要被更新,此时,尚未开始跟新,内存中的虚拟Dom还是旧的
render: 此时,又要重新更新新的state和props 重新渲染一颗内存中的虚拟dom数,当render 调用完毕,内存中的旧Dom树,已经被DOM树替换了?此时页面还是旧的。
componentDidUpdate:此时,页面又被重新渲染了,state和虚拟DOM和页面已经完全保持同步了。

  • 组件销毁阶段 也有一个显著的特点,一辈子只执行一次。

componentwillUnount:组件将要被销毁,此时组件还是可以正常使用

static defaultProps 和 使用prop-types 进行props属性

1.创建一个静态popTypes对象,在这个对象汇总,可以把外界传过来的属性,做类型校验。

  1. 如果要为船体过来的属性做类型校验,必须安装React提供的第三方包,叫做prop-types;
  2. prop-types 大概在v.15之前并没有单独抽离出来,那时候,还和react包在一起。v.15之后官方吧类型校验模块,单独抽离一个包,就叫做prop-types
    终端 yarn add prop-types
    然后 impont ProtTYpes from 'prop-types' 导入
    class Hello2 extends React.Component{
constructor(props){
    super(props);
    this.state ={
        msg:'这是hello1组件的私有数据',
        info:'第二个数据'
    }

}
//在一封装一个组件的时候,组件内容,肯定有一些数据是必须的,哪怕永固没有传递一些启动参数,这时候,组件内部,尽量给自己提供一个默认值。
  // 在React中,使用静态的defaultProps 属性,来设置组件的默认属性值。
  static defaultProps={
    initcount: 0;
  }
  static propTypes={
    initcount:ProtTYpes.number;//这里就是限制值的类型,如果别人传错了,就会在自动打印出错误
}
    render(){
        return <div>防守打法克鲁赛德荆防颗粒 
  // 这里参数传递,只要是props 中的参数都是只读的
  <p> {this.propsinitcount}</p></div>
    }

}

nextState nextProps

在生命周期函数shouldComponentUpdate()中,通过nextState 和nextPorps 来获取到最新的值。
this.state 中获取到的值是上一次获取到的值(旧的值)。

shouldComponentUpdate(nextProps,nextState){

}

在这个函数中,此时页面上的DOM机诶单,都是旧的,应该慎重操作,因为你可能操作的是旧的DOM
componentWillUpdate(){

}

数据的双向绑定

    import React from 'react'

export default class BindComp extends React.Component {
constructor(props){
super(props)
this.state ={
msg:'zheshi msg'
}
}

render(){
    return <div>
            <h1>绑定this并传递参数的烦事 </h1>
            <h2>{this.state.msg}</h2>
            <input type="button" value ="点击改边" onClick={this.changeMsg.bind(this,'haha','hehe')}/>
  //双向绑定必须实现 onChange这个方法
            <input type="text" value={this.state.msg} onChange = {this.textChanged} refs="txt"/>
    </div>;
}

//input 改变的东西
extChanged =(e) =>{
console.log('改变了');
// this.setState({
// console.log(this.refs.txt.value)

    // })
    console.log(e.target.value);
    this.setState ({
        msg:e.target.value
    })
    
}

}

props 传递方法

// 在主建中这样写
<CMTBox reload={this.loadCmts}> </CMTBox>

然后可以在CMTBox 组件中需要的地方调用这个方法

contex特性

  1. 在父组件中,定义一个function,这个function有个固定的名称,叫做getChildContext,内部,必须返回一个对象,这个对象,就是要共享给所有子孙的数据。
getChildContect(){
  return {
    color:this.state.color
    }      
}
  1. 在父组件中,使用属性校验,规定一下传递给 组件的类型,需要定义一个静态的 childContextTypes
    static childContextTypes={
    color:ReactTypes.sting;
    }
  2. 在子组件中使用
    首先也要做一个属性校验
    statc contextypes={
    color:ReactTypes.string.
    }
    然后就可以使用了

react 中fetch api 使用

在React中我没可以使用fetchAPI 来获取数据,fetchApi是基于Promise 封装的

        componentWillMount(){
    fetch('url')
    .then(response=>{
        return response.json()

    })
    .then(data=>{

    })

}

react 中使用fetch-jsonp

在react中使用FetchApi 存在跨域问题,可以使用GitHub上的 fetch-jsonp
https://github.com/camsong/fetch-jsonp

  1. cnpm install fetch-jsonp

  2. import FetchJsonp from 'fetch-jsonp'

  3. 使用

        FetchJsonp('https://api.douban.com/v2/movie/imdb/tt0111161?apikey=0df993c66c0c636e29ecbb5344252a4a')
     .then(response=>{
         return response.json()
    
     })
     .then(data=>{
         console.log(data)
     }) 
    

相关文章

网友评论

      本文标题:reactive

      本文链接:https://www.haomeiwen.com/subject/yqhjuctx.html