[TOC]javascript
組件的特色:vue
無需單獨引用或配置,直接在大組件中調取全局組件便可java
語法:
Vue.component(component.name,options)
node
component.name
組件命名的規則
調取組件的時候,會把因此組件的單詞渲染爲小寫字母**(咱們命名的時候除PasalCase模式外,咱們都要把組件名設置爲小寫,調取組件的時候能夠是大寫也能夠是小寫(最後都是按照小寫渲染 ))vuex
命名的時候儘可能不要出現其他的特殊字符數組
options
可使用的有VM實例具備的一切(DATA,METHODS,生命週期函數)每調用一次組件都是建立一個單獨的VUE實例(VueComponent--->vue)瀏覽器
<body>
<div id="app"> <h3 v-text='title'></h3> // <my-button/> //單閉合:不符合w3c規範,調取完成後,後面的視圖不識別(避免使用) //雙閉合:能夠設置除組件規定內容外的其他內容(slot插槽) <my-button> 我加的其它內容(slot 插槽) //沒有效果,須要使用slot插槽 </my-button> </div> <!-- IMPORT JS --> <script src="./node_modules/vue/dist/vue.js"></script> <script> Vue.component('MyButton', { template: `<button>組件中的按鈕</button>` }); let vm = new Vue({ el: '#app', data: { title: '你們好哇~' } }); </script> </body>
複製代碼
把調取組件時候,寫在組件中間部分的內容獲取到,放置到組件的某個位置(具體位置根據需求來),依託這種方式,可讓當前組件具有更強的擴展性閉包
/* * 必須設置template或者render函數:來規定當前組件的渲染視圖 * 1.只能有一個根元素節點 * 2.template的值能夠是字符串(包裹須要的結構),也能夠把結構單獨分離出來,放置到<template></template>標記中,而後和當前組件關聯 * DATA必須是一個函數:至關於造成一個閉包,讓返回的對象(須要的響應式數據)是當前實例的私有的 */
<body>
<div id="app"> <h3 v-text='msg'></h3> <!-- 調用組件 --> <my-app> <template v-slot:before><p>我是調取組件的時候,在組件模板外單獨寫的內容</p></template> <template #after><p>我是後面的</p></template> </my-app> </div> <!-- TMPLATE:建立TMPLATE標籤用來構建組件渲染的視圖 --> <template id="mybutton"> <div> <slot name='before'></slot> <button @click='handle'>我是template組件{{msg}}</button> <slot name='after'></slot> </div> </template> <script src="./node_modules/vue/dist/vue.js"></script> <script> Vue.component('MyApp', { template: '#mybutton', data() { return { msg: '你好哇~' } }, methods: { handle() { this.msg = '~hello world~' } } }) let vm = new Vue({ el: '#app', data: { msg: 'hello~' } }); </script> </body>
複製代碼
建立組件:let componenName={...}app
基於components屬性聲明組件:想用哪一個組件須要先聲明函數
使用組件
<body>
<div id="app"> <my-button></my-button> </div> <!-- 建立 template 標籤來構建組件渲染視圖--> <template id="MyButtonTemplate"> <div> <button>組件按鈕~{{msg}}</button> <p>哈哈哈</p> </div> </template> <!-- IMPORT JS --> <script src="./node_modules/vue/dist/vue.js"></script> <script> // 1. 建立局部組件 const MyButton = { template:'#MyButtonTemplate', data(){ return{ msg:'hello~' } } }; let vm = new Vue({ el: '#app', /2. 註冊當前視圖中須要使用的局部組件 components:{ MyButton } }) </script> </body>
複製代碼
<my-component title='哈哈哈' :data-index='0'></my-component> //傳遞的屬性值默認都是字符串格式,若是想要讓傳遞的值是數字、布爾、數組、對象等格式,咱們須要使用v-bind處理 複製代碼
Vue.component('my-component',{
props:['title','dataIndex'],
...
})
/* props中聲明的屬性和data同樣,是響應式數據,掛載到vm實例上,可控制視圖渲染 * 命名大小寫:父組件傳遞的是kebab-case格式,props中獲取的是camelCase駝峯命名|pasalCase * 基於屬性傳遞進來的值,只能獲取使用,不能在子組件中修改(修改後會有對應的效果,子組件會從新渲染,可是控制檯會報錯) */
複製代碼
/* 指定屬性的類型:props:{xxx:String,...} * 指定屬性的默認值:props:{xxx:{type:String,default:'xxx',required:true}} - type若是是一個數組,意爲指定的多類型皆能夠 - default能夠是一個函數,函數返回值是默認值 - validator自定義驗證規則函數:必須符合函數中指定的規則,返回true/false */
props: {
//=>指定屬性的類型
props: {
title: String,
dataIndex: [Number, Array]
},
//=>設置默認值
title: {
type: String,
default: '我是設定的屬性默認值'
},
aaa: {
//=>數據格式
type: [Number, Array],
//=>是否爲必傳 TRUE必須傳遞
required: true
//=>自定義驗證規則 val傳遞的屬性值 在函數中,根據本身的規則,返回TRUE和FALSE來驗證傳遞的值是否符合規則
validator(val) {
return val >= 0;
}
}
},
複製代碼
樣式和class自動合併問題
能夠把子組件當作一個標籤,咱們能夠設置ID/CLASS/STYLE等內置屬性值,這些屬性也會傳遞給子組件,VUE幫咱們處理好的,該合併的合併,該覆蓋的覆蓋,無需咱們在PROPS中註冊處理
全部的 prop 都使得其父子 prop 之間造成了一個單向下行綁定:父級 prop 的更新會向下流動到子組件中,可是反過來則不行。
Vue 的父組件和子組件生命週期鉤子函數執行順序能夠歸類爲如下 4 部分:
加載渲染過程:父 beforeCreate -> 父 created -> 父 beforeMount -> 子 beforeCreate -> 子 created -> 子 beforeMount -> 子 mounted -> 父 mounted
子組件更新過程:父 beforeUpdate -> 子 beforeUpdate -> 子 updated -> 父 updated
父組件更新過程:父 beforeUpdate -> 父 updated
銷燬過程:父 beforeDestroy -> 子 beforeDestroy -> 子 destroyed -> 父 destroyed
每次父級組件發生更新時,子組件中全部的 prop 都將會刷新爲最新的值。這意味着你不該該在一個子組件內部改變 prop。若是你這樣作了,Vue 會在瀏覽器的控制檯中發出警告。
子組件想修改時,只能經過
$emit
派發一個自定義事件,父組件接收到後,由父組件修改。有兩種常見的試圖改變一個 prop 的情形 :這個 prop 用來傳遞一個初始值;這個子組件接下來但願將其做爲一個本地的 prop 數據來使用。 在這種狀況下,最好定義一個本地的 data 屬性並將這個 prop 用做其初始值
這個 prop 以一種原始的值傳入且須要進行轉換。 在這種狀況下,最好使用這個 prop 的值來定義一個計算屬性
訂閱自定義事件:調用組件的時候基於屬性傳遞一個方法 (父)
<my-component @func='xxx'></my-component> new Vue({ methods:{ xxx(value){ //=>value是this.$emit時候傳遞的第二個參數值 } } }); 複製代碼
通知自定義事件執行 (子)
{
methods:{
xxx(){
this.$emit('func',10);
}
}
}
複製代碼
let eventBus = new Vue; //=>建立事件總線
//A組件 => 基於$on建立一個自定義事件:把指定方法放到任務隊列中(兄弟)
eventBus.$on('xxxA',this.func);
//B組件=> 通知自定義事件執行
eventBus.$emit('xxxA');
複製代碼
經過this.$children 控制子組件的顯示隱藏
<body>
<div id="app"> <my-vote v-for='item in voteList' :title="item.title"></my-vote> </div> <!-- TEMPLATE --> <template id="MyVoteTemplate"> <div class="container"> <h3> <span v-text='title'></span> (<span v-text='num'></span>) <button type="button" class="btn btn-primary" @click='handle'>點着玩</button> </h3> <vote-button ref='button'></vote-button> </div> </template> <template id="VoteButtonTemplate"> <div class="footer" v-show='flag'> <button type="button" class="btn btn-primary" @click="handle('support')">支持</button> <button type="button" class="btn btn-danger" @click="handle('oppose')">反對</button> </div> </template> <!-- IMPORT JS --> <script src="./node_modules/vue/dist/vue.js"></script> <script> const VoteButton = { template: '#VoteButtonTemplate', methods: { handle(type) { // console.log(this.$parent); this.$parent.num++; } }, data() { return { flag: true } } }; const MyVote = { template: '#MyVoteTemplate', props: ["title"], data() { return { num: 0 } }, components: { VoteButton }, methods: { handle() { // console.log(this.$children); // this.$children[0].flag = !this.$children[0].flag; this.$refs.button.flag = !this.$refs.button.flag; } } }; let vm = new Vue({ el: '#app', data: { voteList: [{ id: 1, title: '哈哈哈' }, { id: 2, title: '呵呵呵' }] }, components: { MyVote } }); // vuex:公共狀態管理 </script> </body> 複製代碼
<body>
<div id="app">
<my-vote v-for='item in voteList' :title="item.title"></my-vote>
</div>
<!-- TMPLATE:建立TMPLATE標籤用來構建組件渲染的視圖 -->
<template id="myVoteTemplate">
<div class="container">
<h3><span v-text='title'></span>(<span v-text='num'></span>)</h3>
<my-content :eventbus='eventBus'></my-content>
<!-- 2.於自定義事件,把父組件的某個方法註冊到任務隊列當中 -->
<my-button @changeparent='changeParent' :eventbus='eventBus'></my-button>
</div>
</template>
<template id="myContentTemplate">
<div class="content">
<p>支持人數:<span v-text='supNum'></span></p>
<p>反對人數:<span v-text='oppNum'></span></p>
<p>支持率:<span v-text='ratio'></span></p>
</div>
</template>
<template id="myButtonTemplate">
<div class="footer">
<button type="button" class="btn btn-success" @click="handle('support')">支持</button>
<button type="button" class="btn btn-danger" @click="handle('oppose')">反對</button>
</div>
</template>
<script src="./node_modules/vue/dist/vue.js"></script>
<script>
/* 1. 點擊子組件影響父組件的數據
*/
// let eventBus = new Vue;
const myContent = {
template: '#myContentTemplate',
props: ['eventbus'],
data() {
return {
supNum: 0,
oppNum: 0
}
},
computed: {
ratio() {
let total = this.supNum + this.oppNum;
if (total === 0) {
return '0%';
}
return (this.supNum / total * 100).toFixed(2) + '%'
}
},
methods: {
// 1. 建立一個方法(兄弟)
changeNum(type) {
type === 'support' ? this.supNum++ : this.oppNum++;
}
},
created() {
// 2.基於$on建立一個自定義事件:把指定方法放到任務隊列中(兄弟)
this.eventbus.$on('changesupport', this.changeNum)
}
}
const myButton = {
template: '#myButtonTemplate',
props: ['eventbus'],
data() {
return {}
},
methods: {
handle(type) {
// 3.通知任務隊列中changeParent這個事件執行
// 事件類型,後面的參數都是通知方法執行的時候,給方法傳遞的參數
this.$emit('changeparent', type);
// 3.點擊執行handle時,通知自定義事件執行;
this.eventbus.$emit('changesupport', type);
}
}
}
const myVote = {
template: '#myVoteTemplate',
data() {
return {
num: 0,
eventBus: new Vue
}
},
props: ['title'],
components: {
myContent,
myButton
},
//1. 自定義事件(子改父)
methods: {
changeParent(type) {
this.num++;
}
}
}
let vm = new Vue({
el: '#app',
data: {
voteList: [{
id: 1,
title: '今每天氣很好~'
},
{
id: 2,
title: '今每天氣很差~'
},
{
id: 3,
title: '今每天氣還能夠~'
}]
},
components: {
myVote
}
})
</script>
</body>
複製代碼