• React 核心思想之声明式渲染


    React 发展很快,概念也多,本文目的在于帮助初学者理清 React 核心概念。

    React 及 React 生态

    React 的核心概念只有 2 点:

    • 声明式渲染(Declarative)

    • 基于组件(Component-Based)

    声明式渲染

    声明式与命令式

    • 命令式编程:命令“机器”如何去做事情(how),这样不管你想要的是什么(what),它都会按照你的命令实现。

    • 声明式编程:告诉“机器”你想要的是什么(what),让机器想出如何去做(how)。

    举例:

    // 命令式关注如何做(how)
    
    var numbers = [1,2,3,4,5]
    
    var doubled = []
    
    for(var i = 0; i < numbers.length; i++) {
    
      var newNumber = numbers[i] * 2
      doubled.push(newNumber)
    
    }
    console.log(doubled) //=> [2,4,6,8,10]

    遍历整个数组,取出每个元素,乘以二,然后把翻倍后的值放入新数组,每次都要操作这个双倍数组,直到计算完所有元素。

    // 声明式关注做什么(what)
    
    var numbers = [1,2,3,4,5]
    
    var doubled = numbers.map(function(n) {
    
      return n * 2
    })
    console.log(doubled) //=> [2,4,6,8,10]

    map 函数所作的事情是将直接遍历整个数组的过程归纳抽离出来,让我们专注于描述我们想要的是什么(what)。

    模板渲染

    渲染:模板 => HTML => 页面视图

    发生在服务器的叫后端模板渲染,公司用的是velocity

    发生在客户端的叫前端模板渲染,常用的有 artTemplate

    以 artTemplate 为例。

    • 模板

    <script id="test" type="text/html">
        <div>
            <h2>北京时间: {{ date.toLocaleTimeString() }}.</h2>
        </div>
    </script>
    • 数据

    • 渲染

    setInterval(function() {
        // 数据
        var data = {
            date: new Date()
        };
        // 渲染(将数据和模板绑定在)
        var html = template('test', data);
        // 渲染
        document.getElementById('container').innerHTML = html;
    },100)

    React 声明式渲染

    和普通模板不同的是,React 模板写在 JS 文件中,而不是 html 的 <script> 标签中。能使用所有 JS 语法,而不只有模板语法,所以更加灵活。

    function formatName(user) {
      return user.firstName + ' ' + user.lastName;
    }
    
    // 数据
    const user = {
      firstName: 'Harper',
      lastName: 'Perez'
    };
    
    // 模板
    const element = (
      <h1>
        Hello, {formatName(user)}!
      </h1>
    );
    
    // 渲染
    ReactDOM.render(
      element,
      document.getElementById('root')
    );

    React 可局部渲染,且只渲染改变了的数据。纯模板只能整体渲染。

    高效的局部渲染意味着,开发者 只需要维护可变的数据 state (what) ,让 react 框架帮助我们处理 DOM 操作(what)。

    // React.createClass 创建模板容器(类)
    class Clock extends Component {
      render() {
          return (
              <div>
                  <h2>北京时间: { this.props.date.toLocaleTimeString() }</h2>
              </div>
          );
      }
    }
    
    setInterval(function() {
        // ReactDOM.render 渲染指令
        ReactDOM.render(
          // date 数据
          <Clock date={new Date()} />,
          document.getElementById('container')
        );
    }, 100);

    state 只用于存放可变的数据。

    通过 setState 告诉 react 什么数据变了,React 会自动更新数据改变部分的视图

    class Clock extends Component {
      // 初始化
      constructor(props) {
        super(props);
        // state 只用于存放可变的状态
        this.state = {date: new Date()};
      }
      // 初始化完成后执行
      componentDidMount() {
        setInterval(() => {
          // setState 在修改 state 参数后会自动调用 render 方法。
          this.setState({
            date: new Date()
          })
        },100)
      }
    
      render() {
          return <h2>北京时间: { this.state.date.toLocaleTimeString() }</h2>
      }
    }
    
    ReactDOM.render(
      <Clock />,
      document.getElementById('js-main')
    );

    React 通过 diffing 算法计算如何更新视图。而 diffing 算法有个 的假设前提,开发人员会提供给长列表的每个子项一个 ID,帮助算法进行对比。

    function NumberList(props) {
      const numbers = props.numbers;
      const listItems = numbers.map((number) =>
        <li key={number.toString()}>
          {number}
        </li>
      );
      return (
        <ul>{listItems}</ul>
      );
    }
    
    const numbers = [1, 2, 3, 4, 5];
    ReactDOM.render(
      <NumberList numbers={numbers} />,
      document.getElementById('root')
    );

    完成的渲染流程

    初始化的渲染流程分为 3 步。

    第一步,开发者使用 JSX 语法写 React,babel 会将 JSX 编译为浏览器能识别的 React JS 语法。这一步,一般配合 webpack 在本地进行。

    第二步,执行 ReactDOM.render 函数,渲染出虚拟DOM。

    第三步,react 将虚拟DOM,渲染成真实的DOM。

    页面更新的流程同样也是 3 步。

    第一步,当页面需要更新时,通过声明式的方法,调用 setState 告诉 react。

    第二步,react 自动调用组件的 render 方法,渲染出虚拟 DOM。

    第三步,react 会通过 diffing 算法,对比当前虚拟 DOM 和需要更新的虚拟 DOM 有什么区别。然后重新渲染区别部分的真实 DOM。

    原文:https://segmentfault.com/a/1190000007463108#articleHeader0

  • 相关阅读:
    数据结构算法练习(一)
    crontab详解
    git遇到问题
    docker容器管理
    docker及服务器遇到的坑
    shell study
    低级终端IO
    高级IO
    信号处理
    UNIX日期与时间
  • 原文地址:https://www.cnblogs.com/showcase/p/10577563.html
Copyright © 2020-2023  润新知