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 模板寫在 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