前言
本人原為React開發者,現在轉戰Vue。在這些天接觸Vue的日子裡,說說自己的感覺:同樣的登山活動,React就像父親,給你必要的登山工具就讓你出發了;Vue就像母親,在你登山之前為你準備好了所有東西,嘮嘮叨叨了一波,規劃了路線,給了你厚厚的導航指南,才讓你出發。
本文目的
- 方便React開發者更快的上手Vue
- 進行更加詳盡的React以及Vue的開發體驗比較
目標人群
有一定的React開發經驗,正在並行使用Vue的開發者
問題
- Vue的模板跟React中使用的jsx有什麼區別?
- 如何在React中實現Vue模板上帶有的功能?
vue模板與JSX比較
1. 表示式(expressions)
JSX表示式用{}包裹,vue模板表示式用{{}}包裹,其餘一致.
vue模板表示式:
程式碼比較:
<!--vue-->
<template>
<div>
<p>I have a {{ product }}</p>
<p>{{ product + 's' }}</p>
<p>{{ isWorking ? 'YES' : 'NO' }}</p>
<p>{{ product.getSalePrice() }}</p>
</div>
</template>
<!--react-->
<div>
<p>I have a { product }</p>
<p>{ product + 's' }</p>
<p>{ isWorking ? 'YES' : 'NO' }</p>
<p>{ product.getSalePrice() }</p>
</div>
複製程式碼
2.指令(directives)
Vue模板:小夥子,用你的頭髮記好了,有如下指令:
Vue模板指令:
JSX:啥啥啥,你自己實現不就好了嗎。。。
- v-if, v-else-if, v-else JSX直接用萬能的三元表示式
- v-show JSX在dom上新增如下程式碼,實現一樣的功能
style={ifShow ?{} : { display: 'none' }}
複製程式碼
- v-model JSX在對應的dom上繫結事件,事件裡面自己愛怎麼處理怎麼處理
程式碼比較:
<!--vue指令-->
<template>
<div>
<p v-if="container1">你現在看到container1了</p>
<p v-else-if="container2">你現在看到container2了</p>
<p v-else>你現在看到default了</p>
<p v-show="ifShow">影響顯示的p</p>
<input type="text" v-model="inputText"/>
</div>
</template>
<!--react指令-->
<div>
{
container1 ?
<p>你現在看到container1了</p> :
container2 ?
<p>你現在看到container2了</p> :
<p>你現在看到default了</p>
}
<p style={{display: ifShow ? 'block' : 'none'}}></p>
<input type="text" onChange={val => () => {this.setState{inputText:val}}}
value={this.state.inputText}/>
</div>
複製程式碼
3. 列表渲染(list rendering)
Vue模板列表渲染:v-for React JSX: 直接在dom中插入map函式,裡面直接用js來處理引數
<!--vue-->
<template>
<ul>
<li v-for="(item, i) in list" :key="item.id">{{item.text}}</li>
</ul>
</template>
<!--react-->
<div>
<ul>
{
list.map((item, i) => <li key={item.id}>{item.text}</li>)
}
</ul>
</div>
複製程式碼
4. 繫結(binding)
繫結其實就是元件的傳參,通過繫結,將對應的引數傳遞到子元件。常見的繫結有:1、普通屬性繫結;2、style屬性繫結,3、class屬性繫結; Vue的資料繫結:
React JSX: 呵呵,style不是屬性啊?class不是屬性啊?弄那麼複雜幹嘛?!什麼?你們說我們style不支援陣列?你將陣列轉換成物件就好了嗎?你說我們class不支援物件以及陣列?classnames庫瞭解一下。<!--vue繫結-->
<ul>
<li :type="liType"></li>
<!--style支援陣列傳入-->
<li :style="[{backgroundColor: '#fff'}]"></li>
<!--style支援物件傳入 如果變數active為true則新增對應的'active'類-->
<li :style="{active}"></li>
<!--class支援陣列傳入 如果變數active為true則新增對應的'active'類-->
<li :class="[active]"></li>
<!--class支援物件傳入 如果變數active為true則新增對應的'active'類-->
<li :class="{active}"></li>
</ul>
<!--react繫結-->
<ul>
<li type={liType}></li>
<!--style需要支援陣列傳入??自己用函式(將陣列轉為物件)處理吧-->
<li style={this.arrayToObj([{backgroundColor: '#fff'}])}></li>
<!--style支援物件傳入-->
<li style={{backgroundColor: '#fff'}}></li>
<!--class需要支援陣列傳入??自己用函式處理吧,函式都懶得寫?classnames庫瞭解一下-->
<li className={this.arrayToString([{backgroundColor: '#fff'}])}></li>
<!--class需要支援物件傳入??自己用函式處理吧,函式都懶得寫?classnames庫瞭解一下-->
<li className={classnames({active})}></li>
</ul>
複製程式碼
5. 事件處理(actions/events)
Vue模板:記住了,有以下事件處理
JSX:跟js事件名稱一致,直接放置在對應的節點進行事件繫結就好<!--vue-->
<template>
<button v-on:click="handleBtn">我是一個點選按鈕</button>
</template>
<!--react-->
<div>
<button onClick={this.handleBtn}>我是一個點選按鈕</button>
</div>
複製程式碼
總結
Vue模板與JSX的基本使用比較完了,Vue模板為你考慮了很多優化的東西,你只需要記住其中的規則就好,更大的降低了技術門檻。而JSX將更大的控制權留給了程式碼編寫者。
更新
- 2019.03.06 17:29 將v-model.lazy的作用更正為:“當輸入框失去焦點後觸發change事件,才會更改對應的繫結值”(感謝“朝陽群眾-Leo”的指正)
- 2019.03.07 12:51 將“style={{ display: ifShow ? 'block':'none' }}”更正為“style={ifShow ?{} : { display: 'none' }}”--需要考慮元素原來的display屬性,原來的方式會將原有的display屬性覆蓋,可能會影響佈局(感謝“Weijuer”的指正)