vue之component


因為組件是可復用的 Vue 實例,所以它們與 new Vue 接收相同的選項,例如 data、computed、watch、methods 以及生命周期鈎子等。僅有的例外是像 el 這樣根實例特有的選項。

組件基礎:

全局組件:可以在任何(根)實例中使用的組件;

局部組件:只能在某一實例中使用的組件:

一、定義全局組件和局部組件的兩種方法:

方法一:定義一個全局組件和局部組件

全局組件:

let like = Vue.extend({ template: ` <div> <h2>全局組件定義方法一</h2> <p>全局組件定義方法一內容</p> </div> ` }); Vue.component('like-com', like);

局部組件:

let like = Vue.extend({ template: ` <div> <h2>局部組件定義方法一</h2> <p>局部組件定義方法一內容</p> </div> ` }); new Vue({ el: '#app1', components: { 'like-com': like } });

方法二:定義一個全局組件和局部組件

全局組件:

    Vue.component('like', { template: ` <div> <h2>這是一個全局組件</h2> <p>全局組件內容省略!</p> </div> ` });

局部組件:

    new Vue({ el: '#app1', components: { 'love': { template: ` <div> <h2>這是一個局部組件</h2> <p>布局組件內容同樣省略!</p> </div> ` } } });

方法三、使用template定義

<div id="app1"> <my-love></my-love> </div> <template id="temp-com"> <div> <h3>使用template定義的組件</h3> <p>使用template定義的組件的內容!</p> </div> </template>
Vue.component('my-love', { template: '#temp-com' });

方法四、使用script定義

<div id="app1"> <my-love></my-love> </div> <script type="text/template" id="temp-com"> <div> <h3>使用template定義的組件</h3> <p>使用template定義的組件的內容!</p> </div> </script>
Vue.component('my-love', { template: '#temp-com' });

方法五:在模塊系統中局部注冊

你使用了諸如 Babel 和 webpack 的模塊系統。在這些情況下,我們推薦創建一個 components 目錄,並將每個組件放置在其各自的文件中。

然后你需要在局部注冊之前導入每個你想使用的組件。例如,在一個假設的 ComponentB.js 或 ComponentB.vue 文件中:

import ComponentA from './ComponentA' import ComponentC from './ComponentC' export default { components: { ComponentA, ComponentC }, // ... }

現在 ComponentA 和 ComponentC 都可以在 ComponentB 的模板中使用了。

二、父子組件:

let child1 = Vue.extend({ template: ` <p>子組件child1</p> ` }); let child2 = Vue.extend({ template: ` <p>子組件child2</p> ` }); Vue.component('like', { components: { 'child-com1': child1, 'child-com2': child2 }, template: ` <div> <child-com1></child-com1> <child-com2></child-com2> </div> ` });
let child1 = Vue.extend({ template: ` <p>子組件child1</p> ` }); let child2 = Vue.extend({ template: ` <p>子組件child2</p> ` }); new Vue({ el: '#app1', components: { 'child-app1': { components: { 'child-com1': child1, 'child-com2': child2 }, template: ` <div> <child-com1></child-com1> <child-com2></child-com2> </div> ` } } });

三、父子組件通信:從父到子,用props屬性綁定

<div id="app"> <my-comp :username="nickname"></my-comp> </div>
Vue.component('my-comp', { props: ['username'], template: '<h3>{{ username }}</h3>' }); new Vue({ el: '#app', data: { nickname: '小七' } })

五、平行組件傳遞數據:用空實例搭建橋梁

<div id="app"> <huahua></huahua> <shuangdan></shuangdan> </div>
    var Event = new Vue(); Vue.component('huahua', { template: ` <div>我說: <input type="text" @keyup="on_change" v-model="i_said"/></div> `, methods: { on_change: function(){ Event.$emit('huahua-said-something', this.i_said); } }, data: function(){ return { i_said: '' } } }) Vue.component('shuangdan', { template: '<div>花花說:{{huahua_said}}</div>', data: function(){ return { huahua_said: '' } }, mounted: function(){ var me = this; Event.$on('huahua-said-something', function(data){ me.huahua_said = data; }) } }) new Vue({ el: '#app' })

六、prop:

1、在 JavaScript 中對象和數組是通過引用傳入的,所以對於一個數組或對象類型的 prop 來說,在子組件中改變這個對象或數組本身將會影響到父組件的狀態。

2、prop 會在一個組件實例創建之前進行驗證,所以實例的屬性 (如 data、computed 等) 在 default 或 validator 函數中是不可用的。

七、is:

解析 DOM 模板時的注意事項

有些 HTML 元素,諸如 <ul>、<ol>、<table> 和 <select>,對於哪些元素可以出現在其內部是有嚴格限制的。而有些元素,諸如 <li>、<tr> 和 <option>,只能出現在其它某些特定的元素內部。

這會導致我們使用這些有約束條件的元素時遇到一些問題。例如:

<table> <blog-post-row></blog-post-row> </table>

這個自定義組件 <blog-post-row> 會被作為無效的內容提升到外部,並導致最終渲染結果出錯。幸好這個特殊的 is 特性給了我們一個變通的辦法:

<table> <tr is="blog-post-row"></tr> </table>

再比如:

// ul下使用組件
<ul> <li is="component-name"></li> </ul>
//聲明一個組件 new Vue({ components:{ 'component-name':{ template:'<p>你好,這是一個示例</p>' } } })

八、動態組件:使用:is在不同組件之間進行動態切換:

讓多個組件使用同一個掛載點,並動態切換,這就是動態組件。通過 Vue 的 <component> 元素加一個特殊的 is 特性來實現。

    <style>
        .tab-button {
            padding: 6px 10px;
            border-top-left-radius: 3px;
            border-top-right-radius: 3px;
            border: 1px solid #ccc;
            cursor: pointer;
            background: #f0f0f0;
            margin-bottom: -1px;
            margin-right: -1px;
        }
        .tab-button:hover {
            background: #e0e0e0;
        }
        .tab-button.active {
            background: #e0e0e0;
        }
        .tab {
            border: 1px solid #ccc;
            padding: 10px;
        }
    </style>
    <button v-for="tab in tabs" @click="current_tab = tab" :class="['tab-button', {'ctive': current_tab === tab}]">{{tab}}</button> <component :is="get_current_tab" class="tab"></component>
Vue.component('tab_home', { template: `<div>Home component</div>` }); Vue.component('tab_posts', { template: `<div>Posts component</div>` }); Vue.component('tab_archive', { template: `<div>Archive component</div>` }); var vm = new Vue({ el: '#app', data: { current_tab: 'Home', tabs: ['Home', 'Posts', 'Archive'] }, computed: { get_current_tab(){ return 'tab_' + this.current_tab.toLowerCase(); } } });

示例:

<!DOCTYPE html>
<html lang="en" xmlns:v-bind="http://www.w3.org/1999/xhtml" xmlns:v-on="http://www.w3.org/1999/xhtml">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div id="app">
    <component :is="currentTab"></component>
    <button @click="change">切換組件</button>
</div>

<script src="https://cdn.bootcss.com/vue/2.5.17-beta.0/vue.js"></script>
<script>
let home = {template: "<h1>我是主頁</h1>"};
let post = {template: "<h2>我是提交頁</h2>"};
let archive = {template: "<h3>我是存檔頁</h3>"};

let vm = new Vue({
    el: '#app',
    data: {
        index: 0,
        tabs: ['home', 'post', 'archive']
    },
    computed: {
        currentTab: function(){
            return this.tabs[this.index];
        }
    },
    methods: {
        change: function(){
            this.index = (++this.index)%3;
        }
    },
    components: {
        home,
        post,
        archive
    }
});
</script>
</body>
</html>

也可以直接綁定到組件對象上:

<!DOCTYPE html>
<html lang="en" xmlns:v-bind="http://www.w3.org/1999/xhtml" xmlns:v-on="http://www.w3.org/1999/xhtml">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div id="app">
    <component :is="currentTab"></component>
    <button @click="change">切換組件</button>
</div>

<script src="https://cdn.bootcss.com/vue/2.5.17-beta.0/vue.js"></script>
<script>
let vm = new Vue({
    el: '#app',
    data: {
        index: 0,
        tabs: [
            {
                template: '<h1>我是主頁</h1>'
            },
            {
                template: '<h2>我是提交頁</h2>'
            },
            {
                template: '<h3>我是存檔頁</h3>'
            }
        ]
    },
    computed: {
        currentTab: function(){
            return this.tabs[this.index];
        }
    },
    methods: {
        change: function(){
            this.index = (++this.index)%3;
        }
    }
});
</script>
</body>
</html>
Vue.component('tab-home', { template: '<div>Home component</div>' }) Vue.component('tab-posts', { template: '<div>Posts component</div>' }) Vue.component('tab-archive', { template: '<div>Archive component</div>' }) new Vue({ el: '#dynamic-component-demo', data: { currentTab: 'Home', tabs: ['Home', 'Posts', 'Archive'] }, computed: { currentTabComponent: function () { return 'tab-' + this.currentTab.toLowerCase() } } })
  <component v-bind:is="currentTabComponent" class="tab" ></component>

九、在動態組件上使用 keep-alive:

重新創建動態組件的行為通常是非常有用的,但是在有些應用中,我們更希望那些標簽的組件實例能夠被在它們第一次被創建的時候緩存下來。為了解決這個問題,我們可以用一個 <keep-alive> 元素將其動態組件包裹起來。

<!DOCTYPE html>
<html lang="en" xmlns:v-bind="http://www.w3.org/1999/xhtml" xmlns:v-on="http://www.w3.org/1999/xhtml">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div id="app">
    <keep-alive>
        <component :is="currentTab"></component>
    </keep-alive>
    <button @click="change">切換組件</button>
</div>

<script src="https://cdn.bootcss.com/vue/2.5.17-beta.0/vue.js"></script>
<script>
let vm = new Vue({
    el: '#app',
    data: {
        index: 0,
        tabs: [
            {
                template: '<h1>我是主頁</h1>'
            },
            {
                template: '<h2>我是提交頁</h2>'
            },
            {
                template: '<h3>我是存檔頁</h3>'
            }
        ]
    },
    computed: {
        currentTab: function(){
            return this.tabs[this.index];
        }
    },
    methods: {
        change: function(){
            let len = this.tabs.length;
            this.index = (++this.index)%len;
        }
    }
});
</script>
</body>
</html>

條件判斷:

如果有多個條件性的子元素,<keep-alive> 要求同時只有一個子元素被渲染。

<!DOCTYPE html>
<html lang="en" xmlns:v-bind="http://www.w3.org/1999/xhtml" xmlns:v-on="http://www.w3.org/1999/xhtml">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div id="app">
    <keep-alive>
        <home v-if="index===0"></home>
        <posts v-else-if="index===1"></posts>
        <archive v-else></archive>
    </keep-alive>
    <button @click="change">切換組件</button>
</div>

<script src="https://cdn.bootcss.com/vue/2.5.17-beta.0/vue.js"></script>
<script>
let vm = new Vue({
    el: '#app',
    data: {
        index: 0,
    },
    components:{
        home:{template:`<div>我是主頁</div>`},
        posts:{template:`<div>我是提交頁</div>`},
        archive:{template:`<div>我是存檔頁</div>`},
    },
    computed: {
        currentTab: function(){
            return this.tabs[this.index];
        }
    },
    methods: {
        change: function(){
            let len = Object.keys(this.$options.components).length;//獲取組件的個數
            this.index = (++this.index)%len;
        }
    }
});
</script>
</body>
</html>

十、異步組件:

vue開發過程中,我們會做出特別多特別多的組件,包括login,header,footer,main等等。

這樣使整個網站看起來就十分的龐大,當我們在打開網頁的時候,突然一下子把這些所有的組件加載上來,這么多的請求全部同時開始請求,勢必會造成網頁打開很慢,使客戶得到的是非常差勁的體驗。

因此,vue為我們專門設立了異步組件,通過異步組件,我們可以得到兩點好處: 

1、用不到的組件不會加載,因此網頁打開速度會很快,當你用到這個組件的時候,才會通過異步請求進行加載; 

2、緩存組件,通過異步加載的組件會緩存起來,當你下一次再用到這個組件時,絲毫不會有任何的疑遲,組件很快會從緩存中加載出來。

為了簡化,Vue 允許你以一個工廠函數的方式定義你的組件,這個工廠函數會異步解析你的組件定義。Vue 只有在這個組件需要被渲染的時候才會觸發該工廠函數,且會把結果緩存起來供未來重渲染。例如:

<!DOCTYPE html>
<html lang="en" xmlns:v-bind="http://www.w3.org/1999/xhtml" xmlns:v-on="http://www.w3.org/1999/xhtml">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div id="app">
    <async-example></async-example>
</div>

<script src="https://cdn.bootcss.com/vue/2.5.17-beta.0/vue.js"></script>
<script>
Vue.component('async-example', function (resolve, reject) {
    setTimeout(function () {
        // 向 `resolve` 回調傳遞組件定義
        resolve({
            template: '<div>I am async!</div>'
        })
    }, 2000)
});

let vm = new Vue({
    el: '#app',
    data: {
        index: 0,
    }
});
</script>
</body>
</html>

如你所見,這個工廠函數會收到一個 resolve 回調,這個回調函數會在你從服務器得到組件定義的時候被調用。你也可以調用 reject(reason) 來表示加載失敗。這里的 setTimeout 是為了演示用的,如何獲取組件取決於你自己。

一個推薦的做法是將異步組件和 webpack 的 code-splitting 功能一起配合使用:

Vue.component('async-webpack-example', function (resolve) {
  // 這個特殊的 `require` 語法將會告訴 webpack
  // 自動將你的構建代碼切割成多個包,這些包
  // 會通過 Ajax 請求加載
  require(['./my-async-component'], resolve)
})

實例1:

假如你寫一個test.vue文件,在<script>標簽里,實際使用方法如下:

//test.vue的部分
<script>
    import Vue from 'vue'
 
    //關鍵是以下這部分代碼
    //需要將引入的異步組件,賦值給變量searchSearch
    //然后在下方components對象里,將變量正常添加進去,就可以使用異步組件了
    //第一個參數是組件名,第二個是異步引入的方法
    const searchSearch = Vue.component('searchSearch', function (resolve) {
        require(['./service-search.vue'], resolve)
    })
 
    export default{
        data(){
            return {}
        },
        methods: {},
        components: {
            searchSearch: searchSearch
        }
    }
</script>

更簡單的異步組件的使用方法:

<script>
    export default{
        data(){
            return {}
        },
        methods: {},
        components: {
            searchSearch: function (resolve) {
                //異步組件寫法
                require(['./service-search.vue'], resolve)
            }
        }
    }
</script>

可以用到異步組件的地方: 

1、組件中,組件中需要子組件的位置,我們就可以使用異步組件形式;

2、路由中,一般我們打開一個頁面時,其總是會進入其中一個默認的路由,那么其他路由在用不到的時候就沒必要繼續加載,當跳轉到當前路由的時候,再來加載,這里也是使用異步組件非常恰當的地方。

十一、在組件上使用 v-model:

<custom-input v-model="searchText"></custom-input> <span>{{searchText}}</span>
Vue.component('custom-input', { template: `<div><input :value="value" @input="$emit('input', $event.target.value)"/></div>`, props: ['value'] }); new Vue({ el:"#app", data:{ searchText: 'hello' } });

這里的 searchText 的值將會傳入這個名為 value的 prop。同時當 <custom-input> 觸發一個 input 事件並附帶一個新的值的時候,這個 searchText 的屬性將會被更新。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM