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

转载于:https://www.cnblogs.com/showcase/p/10577563.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值