vue學習筆記(三)

一、組件

(一)什么是組件

組件(Component)是 Vue.js最強大的功能之一。組件可以擴展 HTML元素,封裝可重用的代碼組件是自定義元素(對象)。

(二)創建組件的兩種方式

官方推薦組件標簽名是使用-連接的組合詞,例如:<my-hello></my-hello>

1、使用構造器創建組件

使用這種方式創建組件首先需要使用Vue.extend()創建一個組件構造器,然后使用Vue.component(標簽名,組件構造器),根據組件構造器來創建組件。

//1.創建構造器
var MyComponent=Vue.extend({
    template:'<h3>Hello World</h3>'
});
//2.創建組件
Vue.component('my-hello',MyComponent);

//3.使用組件
<div id="app">
    <my-hello></my-hello>
</div>

這種創建組件的方式比較麻煩,使用的較少。

2、直接創建組件

使用Vue.component(標簽名,組件模板),根據組件構造器來創建組件。

//1.創建組件
 Vue.component('my-world', {
    template: '<h2>hello vue.js</h2>'
 });
 
//2.使用組件
<div id="app">
    <my-world></my-world>
</div>

(三)組件的分類

組件分為全局組件和局部組件。

1、全局組件

使用Vue.component()創建的組件都是全局組件。這樣的組件在任何組件內都能使用。上面我們創建就是全局組件。

2、局部組件

局部組件一般都是定義在實例的選項中,稱為實例的子組件。相應的,實例也被稱為父組件。

//1.定義組件
 new Vue({
    el: '#app',
    components: {
        dawei: {
            template: '<h2>my name is dawei</h2>'
        }
    }
});
//2.使用組件
<div id="app">
    <dawei></dawei>
</div>

(四)引用模板

很多時候我們的template模板中需要存放很多標簽內容,這樣的話寫起來會很麻煩。這時候我們可以使用template標簽。

用法如下:

<template id="wbs">    //使用template標簽
    <div>
        <h2>hello {{msg}}</h2>
        <ul>
            <li v-for="value in arr">
                {{value}}
            </li>
        </ul>
    </div>
</template>
    
    new Vue({
        el: '#app',
        components: {
            'my-dawei': {
                template: '#wbs',  //選擇template標簽
                data() {
                    return {
                        msg: 'vue.js',
                        arr: ["a", "b", "c", "d"]
                    }
                }
            }
        }
    });

這里涉及到的幾個知識點得著重提一下:

  • template模板中,所有的元素必須放置在一個根元素中,要不然會報錯。例子中我們將元素放置在了<div>標簽中。

  • 組件中的data選項必須是一個函數類型,使用return返回所有的數據。

(五)動態組件

很多時候項目中需要在某一個地方動態的使用不同的組件,這時候就需要使用動態組件。
動態組件的使用需要綁定is屬性:

<component :is="flag"></component>

簡單示例:

//點擊按鈕顯示不同的組件
 <div id="app">
    <button type="button" @click="flag='my-a'">顯示a組件</button>
    <button type="button" @click="flag='my-b'">顯示b組件</button>

    <component :is="flag"></component>  //傳入flag
</div>

new Vue({
    el: '#app',
    data: {
        flag: 'my-a'   //給flag賦值
    },
    components: {
        'my-a': {
            template: '<p>我是a組件</p>',
        },
        'my-b': {
            template: '<p>我是b組件</p>'
        }
    }
});

(六)keep-alive組件

使用keep-alive組件緩存非活動組件,可以保留狀態,避免重新渲染,默認每次都會銷毀非活動組件并重新創建。

使用范例:

<keep-alive>
     <component :is="flag"></component>
</keep-alive>

 <div id="app">
    <button type="button" @click="flag='my-x'">x</button>
    <button type="button" @click="flag='my-y'">y</button>
    <keep-alive>
        <component :is="flag"></component>
    </keep-alive>
 </div>
 
 new Vue({
    el: '#app',
    data: {
        flag: 'my-x'
    },
    components: {
        'my-x': {
            template: '<p>{{x}}</p>',
            data() {
                return {
                    x: Math.random()
                }
            }
        },
        'my-y': {
            template: '<p>{{y}}</p>',
            data() {
                return {
                    y: Math.random()
                }
            }
        }
    }
 });

這樣的話,第一次產生的隨機數就會被緩存,再次切換的時候也不會發生改變。

二、 組件間數據傳遞

(一)父子組件

在一個組件內部定義另一個組件,那么這對組件稱為父子組件。子組件只能在父組件內部使用。默認情況下,每個組件實例的作用域是獨立的,子組件無法訪問父組件中的數據,同樣,父組件也無法訪問子組件中的數據。


<div id="app">
    <my-a></my-a>
        <!-- 父組件 -->
</div>

<template id="a">
    <div>
        <p>{{msg}}</p> 
        <my-b></my-b>    <!-- 在父組件中調用子組件 -->
    </div>
</template>

<template id="b">
    <div>
        <p>{{mydata}}</p>
    </div>
</template>

<script>
    new Vue({   //根組件
        el: '#app',
        components: {     //子組件寫在components選項中
            "my-a": {     //b組件的父組件
                template: "#a",
                data() {
                    return {
                        msg: '我是父組件',
                    }
                },
                components: { //子組件寫在父組件的components選項中
                    "my-b": {
                        template: "#b",
                        data() {
                            return {
                                mydata: "我是子組件"
                            }
                        }
                    }
                }
            }
        }
    });
</script>

(二)組件間數據傳遞(通信)

1、子組件訪問父組件的數據

步驟:

  • a、調用子組件時,綁定想要獲取的父組件中的數據
  • b、在子組件內部,使用props選項聲明獲取的數據,即接收來自父組件的數據

改進上面的例子:

<div id="app">
    <my-a></my-a>
</div>

<template id="a">
    <div>
        <p>{{msg}}</p> 
        <p>這是要傳遞給子組件的值:{{myname}}</p>
        <my-b :name="myname"></my-b>   <!-- 綁定子組件想要獲取的數據 -->
    </div>
</template>

<template id="b">
    <div>
        <p>{{mydata}}</p>
        <p>這是父組件傳遞過來的數據:{{name}}</p>
    </div>
</template>

<script>
    new Vue({
        el: '#app',
        data: {},
        components: {
            "my-a": {
                template: "#a",
                data() {
                    return {
                        msg: '我是a組件',
                        myname: '子組件b你好,我是父組件a'
                    }
                },
                components: {
                    "my-b": {
                        template: "#b",
                        data() {
                            return {
                                mydata: "我是b組件"
                            }
                        },
                        props: ["name"] //子組件使用props聲明想要獲取的數據
                    }
                }
            }
        }
    });
</script>

2、父組件訪問子組件的數據

步驟:

  • a 在子組件中使用vm.$emit(事件名,數據)觸發一個自定義事件,將數據發送給父組件,事件名自定義
  • b 父組件在使用子組件的地方監聽子組件觸發的事件,并在父組件中定義方法,用來獲取數據
//子組件‘my-b’內部
methods:{
    send(){//使用$emit()觸發一個事件,發送數據,this指當前子組件實例
        this.$emit('e-world', this.senddata);         
    }
}

//在調用子組件的地方監聽子組件觸發的事件,調用自己的方法獲取數據
<my-b @e-world="getData"></my-b>   


 methods: {
    getData(data) {  //參數是子組件傳遞過來的數據
        this.revicedata = data;
    }
 }

3、單向數據流

props是單向數據綁定的,當父組件數據發生變化時,將傳遞給子組件,但是不會反過來。而且不允許子組件直接修改父組件中的數據,強制修改會報錯。

解決方案:

  • 如果子組件想把它作為局部數據來使用,可以將數據存入另一個變量中再操作,不影響父組件中的數據
  • 如果子組件想修改數據并且同步更新到父組件,兩個方法:
    • 使用.sync顯式地觸發一個更新事件(1.0版本中支持,2.0版本中不支持,2.3版本又開始支持)
//使用.sync
 <my-b :name.sync="myname"></my-b> 
 
//子組件修改父組件傳入的值name,觸發update更新事件
this.$emit('update:name', "vuejs"); 
    • 可以將父組件中的數據包裝成對象,然后在子組件中修改對象的屬性(因為對象是引用類型,指向同一個內存空間),推薦使用這種方式。
 data() {
    return { //將要傳遞的數據放入message對象中
        message: {
            hello: '子組件b你好,我是父組件a'
        }
    }
}

<my-b :message="message"></my-b>   //傳遞這個對象給子組件

 methods: {   //在子組件內部修改這個值,這樣就會同步傳遞給父組件。
    edit() {
        this.message.hello = "hahahahh";
    }
 }

4. 非父子組件間的通信

非父子組件間的通信,可以通過一個空的Vue實例作為中央事件總線(事件中心),用它來觸發事件和監聽事件,從而實現非父子組件間的通信。

var Event = new Vue();    //空vue實例

 methods: {  
    send() {  //觸發emit事件
        Event.$emit("hello", this.asmsg);
    }
 }
 
 mounted() {    //在子組件的鉤子函數中監聽該事件
    Event.$on('hello', data => {   //獲取值
        this.bsmsg = data;  
    })
 }

(三)slot內容分發

用來獲取組件中的原內容

var vm = new Vue({
    el: '#app',
    components: {
        'my-hello': {
            template: '#hello'
        }
    }
});

<div id="app">
    <my-hello>hello vue.js</my-hello>
</div>


<template id="hello">
    <div>
        <slot>如果沒有原內容,則顯示該內容</slot>
    </div>
</template>

如果組件標簽中沒有內容就會顯示slot中的內容,這也就是所謂的單個插槽。

還可以對顯示的內容進行分組,這就是具名插槽,可以操作標簽組中的內容:

<div id="app">
    <my-hello>
        <ul slot="s1">
            <li>aaa</li>
            <li>bbb</li>
            <li>ccc</li>
        </ul>
        <ol slot="s2">
            <li>111</li>
            <li>222</li>
            <li>333</li>
        </ol>
    </my-hello>
</div>

<template id="hello">
    <div>
        <slot name="s2"></slot> //為插槽指定名稱  將名為s2的內容放置在這里
        <p>hello vue.js</p>
        <slot name="s1"></slot>  //將名為s1的內容放置在這里
    </div>
</template>

這樣,就可以對組件中的內容實時操作。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,983評論 6 537
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,772評論 3 422
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,947評論 0 381
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,201評論 1 315
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,960評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,350評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,406評論 3 444
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,549評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,104評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,914評論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,089評論 1 371
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,647評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,340評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,753評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,007評論 1 289
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,834評論 3 395
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,106評論 2 375

推薦閱讀更多精彩內容

  • 1.安裝 可以簡單地在頁面引入Vue.js作為獨立版本,Vue即被注冊為全局變量,可以在頁面使用了。 如果希望搭建...
    Awey閱讀 11,066評論 4 129
  • 這篇筆記主要包含 Vue 2 不同于 Vue 1 或者特有的內容,還有我對于 Vue 1.0 印象不深的內容。關于...
    云之外閱讀 5,069評論 0 29
  • Vue 實例 屬性和方法 每個 Vue 實例都會代理其 data 對象里所有的屬性:var data = { a:...
    云之外閱讀 2,231評論 0 6
  • 下載安裝搭建環境 可以選npm安裝,或者簡單下載一個開發版的vue.js文件 瀏覽器打開加載有vue的文檔時,控制...
    冥冥2017閱讀 6,074評論 0 42
  • 風拂起了長發青絲劃過臉暇原來你如此貼近 站在影子里的你睜開雙眼已為你擋住陽光 摩天輪的轉動模糊了落日的余暉眼中的你...
    狼眼閱讀 736評論 3 0