一個新手司機眼裡的 Vue

劉凱里發表於2019-03-04

先說一句題外話,對於 Vue 的探索和應用我只服 ElemeFE

基礎

  • 軟體工程學
  • 程式碼風格
  • 基本功
  • Vue.js 官方文件
  • ES6

Vue 三大特性

資料的雙向繫結

通過資料繫結連線 View 和 Model, 讓資料的變化自動對映為檢視的更新。

資料驅動的元件系統

用巢狀的元件樹來描述使用者介面,每一個元件對應MVVM中的ViewModel。

基於構建工具的單檔案元件系統

藉助webpack強大的loader API,來定義對不同檔案格式的預處理邏輯,從而將 vue 檔案當作 javascript 模組來使用,從而極大提升了程式碼的可複用性。

開始

俗話說“工欲善其事必先利其器”,再往前遞推,工欲利其器必先得其器。在進行一次 vue 專案的開發之前,如何將 vue 引入是我們面對的第一個問題。
這裡我主要介紹兩種引入方式。

傳統的<script>大法

遙想當年,在和jQuery一起玩耍的時候,在每擼一個頁面之前,都會先把jq的cdn路徑放在處於</body>前的<script>裡面,因為這樣做才可以和她愉快的玩耍。
雖說 jq 和 vue 不是一個概念(庫 vs 框架),但是基於瀏覽器解析js的原理,兩者可以用相同的方式引入。

npm install

NPM(Node Package Manager)是Node.js自帶的一款包管理工具,只需要簡單的在鍵盤上敲下
npm install *package name*
就可以將你需要的包安裝至你的專案中,進而藉助模組載入器就可以把她們引入到你的檔案中。
當然,除了npm之外,還有其他的包管理工具,比如 bower 和 yarn,可以根據個人喜好進行選擇。
不過值得一提的是,yarn 是 Facebook 推出的一款包管理工具,他們的工程師在使用 npm 的時候發現了很多需要改進的地方,為了達到預期的效果,打造了 yarn 這款工具。所以,如果你感興趣,可以試試 yarn

評估

對於上面兩種方式的選擇,你需要權衡一些因素:

  • 如果你是嘗試在已有的專案中新增一點新鮮的血液作為預研,建議選擇<script>標籤的形式
  • 如果你是在從零開始搭建一個 vue 專案,建議選擇用包管理工具的方式

為什麼需要構建

要回答這個問題,就要追溯到另外一個問題:在將程式碼釋出到生產環境之前,我們還需要做什麼?
如果能回答好這個問題,我們就會知道——到底為什麼需要構建?
答案可以大致分為以下幾種:

  • 預處理
  • 程式碼風格檢測
  • 資源壓縮
  • 靜態資源替換

因為本文側重點的關係,這裡說一下預處理
這又是另外一個問題了——為什麼需要預處理?
因為無時不刻都在面臨著瀏覽器的相容問題,比如說ES6,一些語法糖寫起來確實很爽,但是並不是所有瀏覽器都認識她;再者,React 的 jsx,Vue 的單檔案,瀏覽器統統不認識,怎麼辦?只能預處理。
這裡推薦 Vue 官方認證的好基友—— Webpack(其實我是gulp粉...)
如果你用的<script>來引入Vue,不用關注這個問題,因為你已經協助瀏覽器進行了“線上編譯”。

元件化

Vue 的 slogan 是:輕量高效的前端元件化方案
這些年,伴隨著 React 對 Web component 的不斷實踐與推動,元件化的思想被前端er們毫無牴觸的接受,相比 React,個人認為 Vue 對元件化的解決方案更加優雅一些——藉助構建工具的單檔案元件系統
在一個.vue檔案中,有三個主標籤:<template>, <script>, <style>,分別對應著當前元件的結構、互動邏輯和樣式。
口說無憑,舉個栗子
先來看看 React 的 JSX

render(){
    let { item } = this.props;

    let children;
    if ( items.length > 0 ) {
        children = (
            <ul>
                { items.map( item =>
                    <li key={item.id}>{item.name}</li>
                ) }
            </ul>
        );
    } else {
        children = <p>No items found.</p>
    }

    return (
        <div className = 'list-container'>
            { children }
        </div>
    );
}複製程式碼

其實看起來也不是多麼的不堪,能夠利用完整的 JavaScript 功能來構建檢視頁面,也是一件有意義的事情。
相同的業務邏輯,用 Vue 來寫

<template>
    <div class="list-container">
        <ul v-if="items.length">
            <li v-for="item in items">{{ item.name }}</li>
        </ul>
        <p v-else>No items found.</p>
    </div>
</template>複製程式碼

是不是比 React 的 jsx 語法和內聯樣式優雅的多呢?
你需要做的就是根據業務邏輯組織好你的 components tree,接著搭配一款模組化方案,就能實現一個基於 Vue 的單檔案元件系統啦。
當然,Vue 也同樣支援 jsx 語法,你也不必非得采用單檔案的組織形式,一切都取決於你的業務以及你的團隊。

Vue Object

每個 Vue 例項在被建立之前都要經過一系列的初始過程。Vue 在這一週期中提供了一些鉤子函式,這就給我麼提供了執行自定義邏輯的機會。

Vue 是否有“控制器”的概念?
答: 沒有。但是你可以將元件的自定義邏輯分佈並實現在這些鉤子函式中。 、

附上一張描述 Vue 物件生命週期的官方神圖 ↓

一個新手司機眼裡的 Vue
一個 Vue 例項的生命週期

做一下簡單的翻譯工作。

beforeCreate

在例項初始化之後,資料觀測(data observer)和 event/watcher 事件配置之前被呼叫。

created

例項已經建立完成之後被呼叫。例項已經完成資料觀測、屬性和方法的運算、watch/event事件回撥,但還沒有開始掛載。

beforeMount

在掛在之前被呼叫

mounted

掛載之後

beforeUpdate

資料更新時呼叫,發生在 vdom 重新渲染和打補丁之前。

updated

由於資料更改導致的 vdom 重新渲染和打補丁,在這之後呼叫。

beforeDestroy

例項銷燬之前呼叫。在這一步,例項仍然完全可用。

destroyed

例項銷燬之後呼叫。

資料流 & 事件流

組裝好了各個元件,你現在面臨的問題是——如何讓這些東西協同工作?

Props

props 是定義在子元件中的屬性,用來定義期望從父元件傳入的資料(在父元件中向子元件新增 v-bind 繫結屬性即可)。

Event

  • 使用$on()監聽事件
  • 使用$emit()觸發事件
  • 使用$dispatch()派發事件,沿父鏈冒泡
  • 使用$broadcast()廣播事件,傳導給所有的後代

有時候,你也許需要一個幫手—— vuex

當應用比較龐大,資料流和狀態也會越發的難以管理和維護,這個時候你就需要 vuex 了。

21秒精通 Vue.js

接下來從一個新手司機的角度,總結一些可以幫助你快速上手 Vue 的小經驗。

不要一上來就用 vue-cli

連手槍都沒打過,你一上來就問我要他孃的義大利炮?(一個出自《亮劍》的梗)

vue-cli是 Vue 官方推出的一款可以快速構建一個 vue app 的腳手架,各項配置也是全到沒誰了。
但是,作為一個剛起步的選手,尤其是當你一開始要去搞的專案沒那麼複雜,還是不要用vue-cli了,原因有以下兩點:

  • 如果你像我一樣(對於構建玩的不是特別6),當你在Terminal按照指引敲擊完幾條命令之後,看著各種配置檔案,肯定會一臉矇蔽,會非常打擊你的學習熱情。
  • 更多的時候,你的專案可能還不需要用到如此完(yōng)整(zhǒng)的構建體系。

所以,自己動手搭一個吧,從最簡單的開始,遲早有一天你也可以寫出一個100%切合自己專案的腳手架。

你不僅需要ES6教程,還需要.babelrc

你是一個有理想的 JavaScript 開發者,你時刻關注著這門語言的發展趨勢,終於有一天,你深深的迷戀上了ES6,她諸多的新特性都令你為之神往,所以你決定緊隨她的腳步。
但事與願違,很多瀏覽器在很大程度上並不認同這位姑娘,所以你需要作為中間人,讓這些觀念老舊的瀏覽器認識到新時代的風尚——這就是編譯(此案例預設為預編譯)。
通常情況下,我們在構建工具中引入babel對自己的指令碼進行語法上的轉換,實現向後相容。
比如在webpack.config.js中引入這樣的規則:

{
    test: /\.js$/,
    loader: 'babel-loader',
    exclude: /node_modules/,
    query: {
        presets: ['es2015', 'stage-0']
    }
}複製程式碼

事實證明,在大多數情況下,這樣是ok的。
但,當我們的專案是藉助構建工具實現的單檔案元件系統時,我們的 JavaScript 都寫在了.vue檔案中,所以當你編譯之後會得到一堆錯誤,這些錯誤都是在你使用ES6語法的地方出現的。
原因是因為我們用vue-loader去處理.vue檔案,這本身沒錯。但是,vue-loader用到了babel-loader,卻沒有配置babel-loader的地方,所以呢,gg。
檢視官方文件,就會找到解決辦法。

“babel-loader respects .babelrc, so it is the recommended approach to configure the Babel presets and plugins.”

參加這裡
綜上,把 babel 相關配置放到 .babelrc 檔案中去

使用組建之前先註冊

想上車?先買票!

元件 (Components) 是 Vue.js 最強大的功能之一。

如果你沒有使用那個單檔案元件系統,在使用元件的時候,你要這麼做 ↓ (註冊一個全域性元件Vue.component(tagName, options)

Vue.component('my-component',{
    // options
});複製程式碼

元件在註冊之後,便可以在父例項的模組中以自定義元素<mu-component></my-component>的形式使用。
要確保在初始化根例項之前註冊了元件

<div id="example">
    <my-component></my-component>
</div>複製程式碼
// 註冊
Vue.component('my-component', {
    template: '<p>Hello Vue component</p>'
});

// 建立根例項
new Vue({
    el: '#example'
});複製程式碼

你也可以通過使用元件例項選項註冊,可以使元件僅在另一個例項/元件的作用域中可用,這也是單檔案元件系統的註冊方式,即區域性註冊
官方文件寫的已經非常詳細了,如果你仍然對這裡有疑慮,給你一個傳送門

父子元件是怎麼協同工作的?

父子元件的關係可以總結為 props down, events up
父元件通過 props 向下傳遞資料給子元件,子元件通過 events 給父元件傳送訊息。
這就好比,老子給兒子生活費(props),兒子一有事就告訴老子:“爸,我沒錢了”、“爸,有人打我”、“爸,我餓了”(events)。

一個新手司機眼裡的 Vue
父子元件協作方式

讓你更方便的除錯 Vue

官方提供了一款 Chrome 外掛,用於除錯你的 Vue app —— Vue.js devtools

最後

全文是從個人的視角出發,描述對 Vue 的認識以及在開發過程中一些問題的理解。
如果有不正確、或是與你理解有偏差的地方,希望你能指出這些問題,共同學習。

一個新手司機眼裡的 Vue
一個還算有趣的前端

相關文章