虚拟dom节点
通过javaScript 来虚拟dom 。通过虚拟的dom 来找到那些需要局部跟新的东西,这样可以提高程序的性能
Diff 算法
新旧Dom数,逐层对比的方式就叫做tree diff,每当我们从前到后,把所有层的节点对完成后,必然能够找到那些需要被更新的元素。
- component diff;在对比每一层的时候,组件之间的对比,叫做component diff
;当对比组件的时候,如果两个组件的类型相同,则暂时认为这个组件不需要被更新,如果组件类型不同,则立即将就组建移除,新建一个组件,替换到被移除的位置。 - element diff:在组件中每个元素也需要对比,那么元素的对比,叫做element diff
- key: key 这个属性可以把页面上的Dom节点和虚拟DOM中的对象,做一层联系关系。
安装环境
-
npm i react react-dom -s
-
在main.js 中导入
import React from 'rect' import ReactDOM from 'rect-dom'
-
创建元素的方法
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'));
- 给组件传对象
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
- 在js中写的jsx 语法(html) 文件中无法自动提示,需要把.js文件改成 .jsx 语法。
- 在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());
- 通过继承的方式,把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 组件的区别
- 使用function 构造函数创建的组件,内部没有state 私有数据,只有一个props来接收外界船体过阿里的数据。
- 使用class 创建的组件,内部,除了有this.props这个只读属性之外,还有一个专门用于窜访自己数据的this.state属性。这个state 是可读写的。
- 基与上面的区别:我们可以为这两种创建组件的方式,下定义了:使用function创建的组件,叫做【无状态组件】用class 创建的组件叫做【有状态组件】
4 . 有状态组件和无状态组件,最本质的区别,就是有无state属性,同时,class 创建的组件,有自己的生命周期函数,但是,funciton创建的组件没有自己的生命周期函数;
什么时候使用有状态组件?
1.如果一个组件需要存放自己的私有数据,或者需要爱组件的不同阶段执行不同的业务逻辑,要使用有状态组件。
- 如果一个组件,只需要根据外界船体过来的props,渲染固定的页面结构就万事了,此时,非常适合使用无状态组件
style样式模块化
- 在webpack.config.js 中为CSS-loader 启用模块化
{test:/.css$/,user:['style-loader','css-loader?modules&loaclIdentName=[name]_[local]-[hash:5]'} - 使用: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对象,在这个对象汇总,可以把外界传过来的属性,做类型校验。
- 如果要为船体过来的属性做类型校验,必须安装React提供的第三方包,叫做prop-types;
- 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特性
- 在父组件中,定义一个function,这个function有个固定的名称,叫做getChildContext,内部,必须返回一个对象,这个对象,就是要共享给所有子孙的数据。
getChildContect(){
return {
color:this.state.color
}
}
- 在父组件中,使用属性校验,规定一下传递给 组件的类型,需要定义一个静态的 childContextTypes
static childContextTypes={
color:ReactTypes.sting;
} - 在子组件中使用
首先也要做一个属性校验
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
-
cnpm install fetch-jsonp
-
import FetchJsonp from 'fetch-jsonp'
-
使用
FetchJsonp('https://api.douban.com/v2/movie/imdb/tt0111161?apikey=0df993c66c0c636e29ecbb5344252a4a') .then(response=>{ return response.json() }) .then(data=>{ console.log(data) })
网友评论