Vue.js:a (re)introduction . 尤雨溪

image.png

英文博客原文:Vue.js: a (re)introduction

Vue.js 是一個(gè)用來開發(fā) web 界面的前端庫余赢。它也有配套的周邊工具。如果把這些東西都算在一起捧弃,那么你也可以叫它一個(gè)『前端框架』跟压。但我個(gè)人更傾向于把它看做是一套可以靈活選擇的工具組合。如果你到現(xiàn)在都還沒聽說過 Vue.js蛤奥,你心里可能在想:前端的幺蛾子就是多佳镜,怎么又來一個(gè)框架?其實(shí) Vue.js 已經(jīng)開發(fā)了兩年多了凡桥。第一次公開發(fā)布則是在 2014 年 2 月蟀伸。這兩年間它一直在不斷進(jìn)化,今天也已經(jīng)有許多人在生產(chǎn)環(huán)境中使用它缅刽。

所以啊掏,Vue.js 到底提供了什么?和其他框架又有何不同衰猛?在已經(jīng)有了 Angular迟蜜、React、Ember 的情況下啡省,為什么要關(guān)注 Vue 娜睛?這篇文章會(huì)簡要地介紹 Vue 的特點(diǎn),希望讀者看完以后能自行判斷卦睹。

響應(yīng)式編程

都說保持狀態(tài)和視圖的同步是困難的畦戒。真的是這樣么?

讓我們從最基本的任務(wù)說起:展示數(shù)據(jù)结序。假設(shè)我們有這樣一個(gè)對(duì)象:

var object = {
  message: 'Hello World!'
}

以及這樣的模板:

<div id="example">
  {{ message }}
</div>

我們可以用 Vue 這樣將兩者綁定:

new Vue({
  el: '#example',
  data: object
})

看上去和渲染模板沒什么兩樣障斋。那么當(dāng)我們改動(dòng)了 object 時(shí),如何更新視圖呢徐鹤?答案是... 你什么都不用做垃环。Vue 已經(jīng)把 object 對(duì)象改造成了一個(gè)『響應(yīng)式對(duì)象』。當(dāng)你修改 object.message 的值時(shí)返敬,渲染的 HTML 會(huì)自動(dòng)更新遂庄。更關(guān)鍵的是,你不需要擔(dān)心你是否因?yàn)槭窃谝粋€(gè) timeout 里面修改了狀態(tài)而需要調(diào)用 $apply劲赠,或是需要調(diào)用 setState()涧团,也不需要給 Flux store 上偵聽一堆事件只磷,更不需要?jiǎng)?chuàng)建一些框架專有的可觀察對(duì)象,比如 ko.observable() 或是 Ember.Object.create() ... It just works泌绣。

Vue 也提供了無縫的『計(jì)算屬性』:

var example = new Vue({
  data: {
    a: 1
  },
  computed: {
    b: function () {
      return this.a + 1
    }
  }
})

// example 實(shí)例會(huì)同時(shí)代理 a 和 b 這兩個(gè)屬性.
example.a // -> 1
example.b // -> 2
example.a++
example.b // -> 3

這里钮追,計(jì)算屬性 b 會(huì)將 a 作為一個(gè)依賴進(jìn)行追蹤,每當(dāng) a 變化阿迈,b 也自動(dòng)跟著變化元媚。你不需要特意去聲明 b 的依賴,因?yàn)檫@本來就不應(yīng)該由你來做苗沧。

組件化

你這個(gè)做小 demo 還不錯(cuò)刊棕,可是大項(xiàng)目呢?

在如何組織復(fù)雜界面的問題上待逞,Vue 和 React 可以說是異曲同工:一切都是組件甥角。我們可以把一開始的那個(gè)例子做成一個(gè)可復(fù)用的組件:

var Example = Vue.extend({
  template: '<div>{{ message }}</div>',
  data: function () {
    return {
      message: 'Hello Vue.js!'
    }
  }
})

// 將該組件注冊(cè)為 <example> 標(biāo)簽
Vue.component('example', Example)

這樣一來我們就可以在其他組件的模板里這樣使用它:

<example></example>

組件可以套其他組件,最終形成一個(gè)代表了你的 UI 視圖的樹狀結(jié)構(gòu)识樱。為了讓組件之間能夠有效的進(jìn)行動(dòng)態(tài)組構(gòu)嗤无,Vue 組件可以:

  • 用 props 來定義如何接收外部數(shù)據(jù);
  • 用自定義事件來向外傳遞消息怜庸;
  • 用 <slot> API 來將外部動(dòng)態(tài)傳入的內(nèi)容(其他組件或是 HTML)和自身模板進(jìn)行組合当犯。

這里就不過多深入細(xì)節(jié)了。有興趣的同學(xué)可以自行查閱官方文檔割疾。

模塊化

都已經(jīng) 2015 年了嚎卫,再不模塊化都不好意思跟人打招呼。

讓我們用一個(gè)模塊打包工具來配合 Vue.js宏榕,比如 Webpack 或者 Browserify拓诸,然后再加上 ES2015。每一個(gè) Vue 組件都可以看做一個(gè)獨(dú)立的模塊麻昼。同時(shí)因?yàn)?Vue 會(huì)自動(dòng)用 Vue.extend 把對(duì)象轉(zhuǎn)化為組件構(gòu)建函數(shù)恰响,我們?cè)谀K里不需要自己調(diào)用 Vue.extend,直接導(dǎo)出一個(gè)對(duì)象即可:

// ComponentA.js
export default {
  template: '<div>{{ message }}</div>',
  data () {
    return {
      message: 'Hello Vue.js!'
    }
  }
}

// App.js
import ComponentA from './ComponentA'

export default {
  // use another component, in this scope only.
  // ComponentA maps to the tag <component-a>
  components: { ComponentA },
  template: `
    <div>
      <p>Now I'm using another component.</p>
      <component-a></component-a>
    </div>
  `
}

看上去還不錯(cuò)涌献。但如果能把一個(gè)組件的模板、樣式和 JavaScript 邏輯都放在同一個(gè)文件里首有,并且有正確的語法高亮燕垃,豈不是更妙?只要配上 vue-loader 或是 vueify井联,我們就能做到:

<!-- MyComponent.vue -->

<!-- css -->
<style>
.message {
  color: red;
}
</style>

<!-- template -->
<template>
  <div class="message">{{ message }}</div>
</template>

<!-- js -->
<script>
export default {
  props: ['message'],
  created() {
    console.log('MyComponent created!')
  }
}
</script>

等一下卜壕!這不就是 Web Components 嗎!而且你的 CSS 依然是全局的呢烙常!

好吧轴捎,這確實(shí)很像是閹割版的 Web Components鹤盒,但是:

  • Vue 文件格式可以支持局部 CSS,只要在 <style> 標(biāo)簽上加上一個(gè) scoped 屬性侦副。并且一個(gè)組件的局部 CSS 不會(huì)像單純的選擇器嵌套那樣『滲透』到它包含的子組件當(dāng)中去侦锯。
  • 每一個(gè) Vue 組件最終都被編譯為純粹的 JavaScript 模塊,并且不需要任何瀏覽器 polyfill 即可支持到最低 IE9秦驯。如果你想尺碰,你也可以把它包在一個(gè)原生的自定義元素中。
  • Vue 文件的 <script> 默認(rèn)支持 ES2015译隘。
  • 你可以在每一個(gè)語言塊中使用任何你想用的預(yù)處理器亲桥。
  • 當(dāng)使用 Webpack + vue-loader 時(shí),你可以借助 Webpack 的強(qiáng)大功能將靜態(tài)資源作為模塊依賴來處理固耘。

所以题篷,只要你想,你就可以寫這個(gè)樣子的 Vue 組件:

image

哦對(duì)了厅目,我有沒有提到番枚,Vue 組件支持熱替換

動(dòng)畫

Vue 能用來做酷炫的東西不璧瞬?

Vue 自帶簡潔易用的過渡動(dòng)畫系統(tǒng)户辫。有很多獲獎(jiǎng)的互動(dòng)類網(wǎng)站是用 Vue 開發(fā)的。

Vue 的反應(yīng)式系統(tǒng)也使得它可以用來開發(fā)高效的數(shù)據(jù)驅(qū)動(dòng)的逐幀動(dòng)畫嗤锉。這一類逐幀動(dòng)畫在基于臟檢查或是 Virtual DOM 的框架中渔欢,往往會(huì)導(dǎo)致性能問題,因?yàn)榧词怪皇歉牧艘粋€(gè)值瘟忱,整個(gè)所處的子樹(scope 或是 component)都需要重新計(jì)算奥额。而 Vue 則是改了多少,計(jì)算多少访诱,不會(huì)有無謂的浪費(fèi)垫挨。在小 demo 中,臟檢查或是 Virtual DOM 往往也足夠快触菜,但是在大型應(yīng)用中可就不一定了九榔。而且,即使足夠快涡相,那些浪費(fèi)的計(jì)算也會(huì)無謂地消耗用戶設(shè)備的電池哲泊。雖然在 React 中可以通過 shouldComponentUpdate 或是 Immutable data 來優(yōu)化,但這都是額外的開發(fā)成本 - 相比之下催蝗,Vue 在此類用例中默認(rèn)就是最優(yōu)化狀態(tài)切威。

一個(gè)用 Vue 配合逐幀動(dòng)畫的例子

路由

做單頁應(yīng)用,沒有路由怎么行丙号?

和 React 一樣先朦,Vue 本身是不帶路由功能的缰冤。但是,有 vue-router 這個(gè)可選的庫來配合喳魏。vue-router 讓你可以將嵌套的路徑映射到嵌套的組件棉浸,并且提供了細(xì)致的路徑跳轉(zhuǎn)控制。這里是個(gè)簡單的例子:

import Vue from 'vue'
import VueRouter from 'vue-router'
import App from './app.vue'
import ViewA from './view-a.vue'
import ViewB from './view-b.vue'

Vue.use(VueRouter)

const router = new VueRouter()

router.map({
  '/a': { component: ViewA },
  '/b': { component: ViewB }
})

router.start(App, '#app')

app.vue 的模板:

<div>
  <h1>This is the layout that won't change</h1>
  <router-view><!-- matched component renders here --></router-view>
</div>

如果你想看一個(gè)更全面的實(shí)例截酷,可以參考 vue-hackernews涮拗。這個(gè)小應(yīng)用用到了 Vue, vue-router, Webpack 和 vue-loader。

穩(wěn)定性

這是個(gè)個(gè)人項(xiàng)目迂苛,會(huì)不會(huì)不穩(wěn)定啊三热。

是的,這是個(gè)個(gè)人項(xiàng)目三幻,背后并沒有大公司支持的全職團(tuán)隊(duì)就漾。但是,數(shù)據(jù)往往更有說服力念搬。從 0.11 版本開始抑堡,Vue 的每一個(gè) commit 都保持了 100% 的測試覆蓋率,并且將一直保持朗徊;GitHub 上的 1400 多個(gè) issue 平均在 13 小時(shí)內(nèi)關(guān)閉首妖。在我寫下這篇文章的同時(shí),尚未修復(fù)的可重現(xiàn)的 bug 數(shù)量為:爷恳。

Vue 近日剛剛發(fā)布了 1.0有缆,現(xiàn)在已經(jīng)適合應(yīng)用于生產(chǎn)環(huán)境中。如果你是從 0.12 升級(jí)到 1.0温亲,則有配套的升級(jí)版本棚壁,全面兼容 0.12 并且?guī)в屑嫒菪缘奶崾揪妗R院蟮乃袔в胁患嫒葑兓陌姹菊恍椋紩?huì)用這樣的方式升級(jí)袖外。

希望這篇文章讓你對(duì) Vue 有了一個(gè)比較大致的了解。我相信相對(duì)于市面上的現(xiàn)有方案魂务,Vue 有著其獨(dú)特的存在價(jià)值曼验。

文章原鏈接 https://zhuanlan.zhihu.com/p/20302927

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市粘姜,隨后出現(xiàn)的幾起案子鬓照,更是在濱河造成了極大的恐慌,老刑警劉巖相艇,帶你破解...
    沈念sama閱讀 216,919評(píng)論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異纯陨,居然都是意外死亡坛芽,警方通過查閱死者的電腦和手機(jī)留储,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,567評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來咙轩,“玉大人获讳,你說我怎么就攤上這事』詈埃” “怎么了丐膝?”我有些...
    開封第一講書人閱讀 163,316評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長钾菊。 經(jīng)常有香客問我帅矗,道長,這世上最難降的妖魔是什么煞烫? 我笑而不...
    開封第一講書人閱讀 58,294評(píng)論 1 292
  • 正文 為了忘掉前任浑此,我火速辦了婚禮,結(jié)果婚禮上滞详,老公的妹妹穿的比我還像新娘凛俱。我一直安慰自己,他們只是感情好料饥,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,318評(píng)論 6 390
  • 文/花漫 我一把揭開白布蒲犬。 她就那樣靜靜地躺著,像睡著了一般岸啡。 火紅的嫁衣襯著肌膚如雪原叮。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,245評(píng)論 1 299
  • 那天凰狞,我揣著相機(jī)與錄音篇裁,去河邊找鬼。 笑死赡若,一個(gè)胖子當(dāng)著我的面吹牛达布,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播逾冬,決...
    沈念sama閱讀 40,120評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼黍聂,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼!你這毒婦竟也來了身腻?” 一聲冷哼從身側(cè)響起产还,我...
    開封第一講書人閱讀 38,964評(píng)論 0 275
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎嘀趟,沒想到半個(gè)月后脐区,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,376評(píng)論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡她按,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,592評(píng)論 2 333
  • 正文 我和宋清朗相戀三年牛隅,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了炕柔。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,764評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡媒佣,死狀恐怖匕累,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情默伍,我是刑警寧澤欢嘿,帶...
    沈念sama閱讀 35,460評(píng)論 5 344
  • 正文 年R本政府宣布,位于F島的核電站也糊,受9級(jí)特大地震影響炼蹦,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜显设,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,070評(píng)論 3 327
  • 文/蒙蒙 一框弛、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧捕捂,春花似錦瑟枫、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,697評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至允悦,卻和暖如春膝擂,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背隙弛。 一陣腳步聲響...
    開封第一講書人閱讀 32,846評(píng)論 1 269
  • 我被黑心中介騙來泰國打工架馋, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人全闷。 一個(gè)月前我還...
    沈念sama閱讀 47,819評(píng)論 2 370
  • 正文 我出身青樓叉寂,卻偏偏與公主長得像,于是被迫代替她去往敵國和親总珠。 傳聞我的和親對(duì)象是個(gè)殘疾皇子屏鳍,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,665評(píng)論 2 354