浅谈React和VDom关系

组件化

  1. 组件的封装
  2. 组件的复用

组件的封装

  • 视图
  • 数据
  • 视图和数据之间的变化逻辑
import React, {Component} from 'react';

export  default class List extends Component{
    constructor(props){
        super(props);
        this.state = { //数据
            list:this.props.data,
        }
    }
    render() { 
        return (
            <div> 
                <ul>
                    {this.state.list.map(function(item,index){
                        return (<li key={index}>{item}</li>);
                    })}
                </ul>
            </div>
        )
    }
}

组件的复用(通过props传递)

import React, {Component} from 'react';
import List from './list'; //组件
import Title from './title';//组件
export  default class Todo extends Component{
    constructor(props){
        super(props);
        this.state = {
            list:['Foo','Bar'],
        }
    }
    todoList (item){
        this.state.list.push(item);
        const newList=this.state.list;
        this.setState({
            list:newList,
        })
    }
    render() {
        return (
           <div>
               <Title todoList={this.todoList.bind(this)} /> 
               <List data={this.state.list}/>
               <Title todoList={this.todoList.bind(this)} /> //复用
               <List data={[1,2,3]}/> //复用
           </div>
        )
    }
}

JSX

React引入JSX,并将它作为了一个独立的标准开放,React.createElement也是可以自定义去修改的,

jsx语法(语法糖)需要转成js

ReactElement createElement(  // 参数——标签属性子元素
  string/ReactClass type,  
  [object props],  
  [children ...]  
)  

  

npm i babel-cli -g

npm i --save-dev babel-plugin-transform-react-jsx

新建.babelrc文件,添加

{
  "plugins": ["transform-react-jsx"]
}

在项目根目录中运行babel --plugins transform-react-jsx src/components/todo/index.js

经过编译:转化成React.createElement,类似于vitual dom 的 h 函数 

import React, { Component } from 'react';
import List from './list'; //组件
import Title from './title'; //组件
export default class Todo extends Component {
    constructor(props) {
        super(props);
        this.state = {
            list: ['Foo', 'Bar']
        };
    }
    todoList(item) {
        this.state.list.push(item);
        const newList = this.state.list;
        this.setState({
            list: newList
        });
    }
    render() {
        return React.createElement(
            'div', //直接渲染
            null,
            React.createElement(Title, { todoList: this.todoList.bind(this) }), //转化成React.createElement
            React.createElement(List, { data: this.state.list }), //List 是自定义构造函数,List 组件必须有render
            React.createElement(Title, { todoList: this.todoList.bind(this) }),
            React.createElement(List, { data: this.state.list })
        );
    }
}

React.createElement(List, { data: this.state.list }), //List 是自定义构造函数,List 组件必须有render
相当于var list = new List({data: this.state.list});
var vNode = list.render(); //通过层层的render函数,最终React.createElement html标签

  

在文件开始添加 /* @jsx h */ 改变 React.createElement

/* @jsx h */
import React, { Component } from 'react';
import List from './list'; //组件
import Title from './title'; //组件
export default class Todo extends Component {
    constructor(props) {
        super(props);
        this.state = {
            list: ['Foo', 'Bar']
        };
    }
    todoList(item) {
        this.state.list.push(item);
        const newList = this.state.list;
        this.setState({
            list: newList
        });
    }
    render() {
        return h(
            'div',
            null,
            h(Title, { todoList: this.todoList.bind(this) }),
            h(List, { data: this.state.list }),
            h(Title, { todoList: this.todoList.bind(this) }),
            h(List, { data: this.state.list })
        );
    }
}

  

JSX中的VDom体现

jsx就是模版,最终需要转化成html,初次渲染,修改state后的setState 的re-render,正好适用于vDOM  

ReactDOM.render(<App />, document.getElementById('root')); //初次渲染 <App /> JSX对象
//通过vDom的patch(container,vnode),而对于re-render是通过setState
todoList (item){
    this.state.list.push(item);
    const newList=this.state.list;
    this.setState({ //re-render patch(vnode,newVnode)
        list:newList,
    })
}

  

源码下载  

该随笔相关代码已上传到github,地址:https://github.com/10086XIAOZHANG/ReactVisualDomDemo  

    

原文地址:https://www.cnblogs.com/fuGuy/p/9226248.html