React 核心思想之聲明式渲染

React 發展很快,概念也多,本文目的在於幫助初學者理清 React 核心概念。javascript

React 及 React 生態html

React 的核心概念只有 2 點:前端

  • 聲明式渲染(Declarative)java

  • 基於組件(Component-Based)react

聲明式渲染

聲明式與命令式

  • 命令式編程:命令「機器」如何去作事情(how),這樣無論你想要的是什麼(what),它都會按照你的命令實現。webpack

  • 聲明式編程:告訴「機器」你想要的是什麼(what),讓機器想出如何去作(how)。git

舉例:github

// 命令式關注如何作(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]

遍歷整個數組,取出每一個元素,乘以二,而後把翻倍後的值放入新數組,每次都要操做這個雙倍數組,直到計算完全部元素。web

// 聲明式關注作什麼(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

相關文章
相關標籤/搜索