Vue.js 學習筆記之四:Vue 組件基礎

到目前為止,這個系列的筆記所展示的都是一些極為簡單的單頁面 Web 應用程序,並且頁面上通常只有幾個簡單的交互元素。但在實際生產環境中,Web 應用程序的用戶界面往往是由多個複雜的頁面共同組成的。這時候,我們就需要開始注意代碼的可復用性了,針對這個問題,Vue.js 框架提出的解決方案就是先將用戶界面上的元素按照不同的功能劃分成一個個獨立的組件,例如導航欄、公告欄、數據表格、用戶註冊表單、用戶登錄界面等。這樣一來,我們在之後的工作中就可以像玩樂高玩具一樣,根據需要將這些組件組合成各種具體的應用程序了。總而言之,組件系統是我們在學習 Vue.js 框架中必須要掌握的一個重要概念。下面,這篇筆記將通過編寫一系列實驗示例來體驗一下在 Vue.js 框架中構建和使用組件的基本方法。

在所有實驗開始之前,我需要先在code目錄中創建一個名為00_test的目錄,以便用於存放接下來的一系列實驗項目,由於這些項目只能用於體驗 Vue 組件的構建與使用方法,並沒有實際的應用功能,所以我給了它00這個編號。那麼,下面就來開始第一個實驗吧!為此,我需要繼續在code/00_test目錄中再創建一個名為component_1的實驗目錄,並在該目錄下執行npm install vue命令來安裝 Vue.js 框架。最後,我只需在code/00_test/component_1目錄下創建一個名為index.htm的文件,並輸入如下代碼:

<!DOCTYPE html>
<html lang="zh-cn">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA  -Compatible" content="ie=edge">
    <title>學習 vue 組件實驗(1):組件註冊</title>
`</head>
<body>
    <div id="app">
        <say-hello :who="who"></say-hello>
        <welcome-you :who="who"></welcome-you>
    </div>
    <script src="./node_modules/vue/dist/vue.js"></script>
    <script>
        // 全局組件註冊
        Vue.component('say-hello', {
            template: `<h1>你好, {{ you }}!</h1>`,
            props: ['who'],
            data: function() {
                return {
                    you: this.who
                };
            }
        });

        const app = new Vue({
            el: '#app',
            // 局部組件註冊
            components: {
                'welcome-you': {
                    template: `<h2>歡迎你, {{ you }}!</h2>`,
                    props: ['who'],
                    data: function() {
                        return {
                            you: this.who
                        };
                    }
                }
            },
            data: {
                who: 'vue'
            }
        });
    </script>
</body>
</html>

在上述實驗中,我用兩種不同的方式分別創建並註冊了say-hellowelcome-you兩個組件。接下來就藉由這兩個組件來介紹一下這兩種組件的使用。首先是say-hello組件,該組件是通過調用Vue.component()方法來創建並註冊到應用程序中的,使用該方法創建的組件通常被稱之為”全局組件”,我們在調用它的時候需要提供兩個參數:

  • 第一個參數應該是一個字符串對象,用於指定組件的名稱,該名稱也是我們要在 HTML 文檔中使用的自定義標籤元素,而由於 HTML 代碼是大小寫不敏感的,所以我個人會建議大家在給組件起名字的時候應該盡量一律使用小寫字母,單詞之間可以使用-這樣分隔符進行區隔。

  • 第二個參數應該是一個 JavaScript 對象,用於設置組件的各項具體參數。這裡定義了以下三項最基本參數:

    • template:該參數是個字符串對象,用於指定該組件的 HTML 模版代碼,需要注意的是,這段代碼說對應的 DOM 對象必須有且只能有一個根節點。而這個對象在最終的 HTML 文檔中將會由該組件所對應自定義標籤所代表,在這裡就是<say-hello>
    • props:該參數是一個字符串數組,該數組中的每個元素都是該組件所對應的自定義標籤的一個屬性,該組件的用戶可以通過v-bind指令將該屬性綁定到某一數據上,以便將數據傳到組件內部。例如在這裡,我在<say-hello>標籤中就用v-bind指令將該標籤的who屬性綁定到了 Vue 實例對象的who數據上,並將其傳進say-hello組件中。
    • data:該參數是一個函數,用於設置組件自身的數據,例如這裡的you,我將從調用者那裡獲取的who數據賦值給了它。對於後者,我們可以用this引用來獲取。

    當然了,除了上面三個基本參數之外,我們還可以為組件設置更多參數,例如自定義事件及其處理函數等,這些我將會在後續的程序編寫體驗中展示。

下面,我們再來看welcome-you組件的構建。如你所見,該組件是在 vue 實例的components成員中構建並註冊到應用程序中的,使用該方法創建的組件通常被稱之為”局部組件”(它與全局組件的區別是,全局組件會在程序運行時全部加載,而局部組件只會在被實際用到時加載) 。該components成員的值也是一個 JSON 格式的數據對象,該數據對象中的每一個成員都是一個局部組件,這些組件採用鍵/值對的方式來定義,鍵對應的是組件的名稱,值對應的是組件參數的設置。當然了,由於局部組件的命名規則與具體參數的設置方法都與全局對象一致,這裡就不再重複說明了。

需要注意的是,第一個實驗項目的編寫方式將 HTML 代碼、Vue 實例的構建代碼以及組件的構建代碼糅合在了一起,這對於提高代碼的可復用性這個目的來說,顯然是不行的。要想解決這個問題,我們可以利用 ES6 規範新增的模塊規則將這三部分代碼隔離開來。為了體驗這種用法,我繼續開始了第二個實驗。具體做法就是在code/00_test目錄中再創建一個名為component_2的實驗目錄,並在該目錄下執行npm install vue命令來安裝 Vue.js 框架。最後,我只需在code/00_test/component_2目錄下創建一個名為index.htm的文件,並輸入如下代碼:

<!DOCTYPE html>
<html lang="zh-cn">
<head>
    <meta charset="UTF-8">
    <script src="./node_modules/vue/dist/vue.js"></script>
    <script type="module" src="./main.js"></script>
    <title>學習 vue 組件實驗(2):以 ES6 模塊的方式註冊組件</title>
</head>
<body>
    <div id="app">
        <say-hello :who="who"></say-hello>
    </div>
</body>
</html>

在上述 HTML 代碼中,我們在照常引入 vue.js 框架之後,使用模塊的方式引入了main.js腳本文件,最好在<div id="app">標籤中使用了後面將要定義的組件所對應的自定義標籤。接下來,我只需要在相同的目錄下創建一個名為main.js的 JavaScript 腳本文件,並在其中輸入如下代碼:

// import Vue from './node_modules/vue/dist/vue.js';
import sayhello from './sayhello.js';

const app = new Vue({
    el: '#app',
    components: {
        'say-hello': sayhello
    },
    data: {
        who:'vue'
    }
});

在上述 JavaScript 代碼中,我首先使用了 ES6 新增的import-from語句導入了後續要在sayhello.js文件中構建的組件,然後在構建 Vue 實例時將其註冊成了局部組件。最後,我只需在同一目錄下再創建這個sayhello.js腳本文件,並在其中輸入如下代碼:

const tpl = `
    <div>
        <h1>你好, {{ you }}!</h1>
        <input type="text" v-model="you" />
    </div>
`;

const sayhello = {
    template: tpl,
    props : ['who'],
    data : function() {
        return {
            you: this.who
        }
    }
};

export default sayhello;

在這部分代碼中,我先定義了一個局部組件,然後再使用 ES6 新增的export default語句將其導出為模塊。當然了,考慮到各種 Web 瀏覽器對 ES6 規範的實際支持情況,以及 Vue.js 框架本身使用的是 CommonJS 模塊規範,所以上述實驗依然可能不是編寫 Vue.js 項目的最佳方式,其中可能還需要配置 babel 和 webpack 這樣的轉譯和構建工具來輔助。當然了,如果大家不想陷入如此複雜的配置,那使用 Vue 官方提供的 vue-cli 腳手架工具是一個不錯的選擇,在下一篇筆記中,我就來記錄如何使用這個工具來構建具體的 vue 應用程序。