定義Vue組件
什么是組件: 組件的出現(xiàn),就是為了拆分Vue實(shí)例的代碼量的钱反,能夠讓我們以不同的組件,來(lái)劃分不同的功能模塊,將來(lái)我們需要什么樣的功能面哥,就可以去調(diào)用對(duì)應(yīng)的組件即可乙各; 組件化和模塊化的不同:
模塊化: 是從代碼邏輯的角度進(jìn)行劃分的;方便代碼分層開(kāi)發(fā)幢竹,保證每個(gè)功能模塊的職能單一耳峦;
-
組件化: 是從UI界面的角度進(jìn)行劃分的;前端的組件化焕毫,方便UI組件的重用蹲坷;
全局組件定義的三種方式
-
使用 Vue.extend 配合 Vue.component 方法:
var login = Vue.extend({ template: '<h1>登錄</h1>' }); Vue.component('login', login);
-
直接使用 Vue.component 方法:
Vue.component('register', { template: '<h1>注冊(cè)</h1>' });
-
將模板字符串,定義到script標(biāo)簽種:
<script id="tmpl" type="x-template"> <div> <a href="#">登錄</a> | <a href="#">注冊(cè)</a> </div> </script>
同時(shí)邑飒,需要使用 Vue.component 來(lái)定義組件:
Vue.component('account', { template: '#tmpl' });
-
注意: 組件中的DOM結(jié)構(gòu)循签,有且只能有唯一的根元素(Root Element)來(lái)進(jìn)行包裹!
組件中展示數(shù)據(jù)和響應(yīng)事件
-
在組件中疙咸,
data
需要被定義為一個(gè)方法县匠,例如:Vue.component('account', { template: '#tmpl', data() { return { msg: '大家好!' } }, methods:{ login(){ alert('點(diǎn)擊了登錄按鈕'); } } });
【重點(diǎn)】為什么組件中的data屬性必須定義為一個(gè)方法并返回一個(gè)對(duì)象
- 組件可以有自己的data數(shù)據(jù)
- 組件的data和實(shí)例的data有點(diǎn)不一樣撒轮, 實(shí)例中的data 可以為一個(gè)對(duì)象,但是組件中的data必須是一個(gè)方法
- 組件中的data除了必須為一個(gè)方法之外乞旦, 這個(gè)方法內(nèi)部,還必須返回一個(gè)對(duì)象才行;
- 組件中的data數(shù)據(jù),使用方式题山,和實(shí)例中的data使用方式完全樣!! !
- 不同組件之間的數(shù)據(jù)不相互影響兰粉,所以data定義為方法
- 在子組件中,如果將模板字符串顶瞳,定義到了script標(biāo)簽中玖姑,那么,要訪問(wèn)子組件身上的
data
屬性中的值慨菱,需要使用this
來(lái)訪問(wèn)焰络;
使用components
屬性定義局部子組件
-
組件實(shí)例定義方式:
<script> // 創(chuàng)建 Vue 實(shí)例,得到 ViewModel var vm = new Vue({ el: '#app', data: {}, methods: {}, components: { // 定義子組件 account: { // account 組件 template: '<div><h1>這是Account組件{{name}}</h1><login></login></div>', // 在這里使用定義的子組件 components: { // 定義子組件的子組件 login: { // login 組件 template: "<h3>這是登錄組件</h3>" } } } } }); </script>
-
引用組件:
<div id="app"> <account></account> </div>
使用flag
標(biāo)識(shí)符結(jié)合v-if
和v-else
切換組件
-
頁(yè)面結(jié)構(gòu):
<div id="app"> <input type="button" value="toggle" @click="flag=!flag"> <my-com1 v-if="flag"></my-com1> <my-com2 v-else="flag"></my-com2> </div>
-
Vue實(shí)例定義:
<script> Vue.component('myCom1', { template: '<h3>奔波霸</h3>' }) Vue.component('myCom2', { template: '<h3>霸波奔</h3>' }) // 創(chuàng)建 Vue 實(shí)例符喝,得到 ViewModel var vm = new Vue({ el: '#app', data: { flag: true }, methods: {} }); </script>
使用:is
屬性來(lái)切換不同的子組件
-
組件實(shí)例定義方式:
// 登錄組件 const login = Vue.extend({ template: `<div> <h3>登錄組件</h3> </div>` }); Vue.component('login', login); // 注冊(cè)組件 const register = Vue.extend({ template: `<div> <h3>注冊(cè)組件</h3> </div>` }); Vue.component('register', register); // 創(chuàng)建 Vue 實(shí)例闪彼,得到 ViewModel var vm = new Vue({ el: '#app', data: { comName: 'login' }, methods: {} });
-
使用
component
標(biāo)簽,來(lái)引用組件洲劣,并通過(guò):is
屬性來(lái)指定要加載的組件:<div id="app"> <a href="#" @click.prevent="comName='login'">登錄</a> <a href="#" @click.prevent="comName='register'">注冊(cè)</a> <hr> <transition mode="out-in"> <component :is="comName"></component> </transition> </div>
-
添加切換樣式:
<style> .v-enter, .v-leave-to { opacity: 0; transform: translateX(30px); } .v-enter-active, .v-leave-active { position: absolute; transition: all 0.3s ease; } h3{ margin: 0; } </style>
父組件向子組件傳值
-
組件實(shí)例定義方式备蚓,注意:一定要使用
props
屬性來(lái)定義父組件傳遞過(guò)來(lái)的數(shù)據(jù)<script> // 創(chuàng)建 Vue 實(shí)例课蔬,得到 ViewModel var vm = new Vue({ el: '#app', data: { msg: '這是父組件中的消息' }, components: { son: { template: '<h1>這是子組件 --- {{finfo}}</h1>', props: ['finfo'] } } }); </script>
-
使用
v-bind
或簡(jiǎn)化指令囱稽,將數(shù)據(jù)傳遞到子組件中:<div id="app"> <son :finfo="msg"></son> </div>
子組件向父組件傳值
原理:父組件將方法的引用,傳遞到子組件內(nèi)部二跋,子組件在內(nèi)部調(diào)用父組件傳遞過(guò)來(lái)的方法战惊,同時(shí)把要發(fā)送給父組件的數(shù)據(jù),在調(diào)用方法的時(shí)候當(dāng)作參數(shù)傳遞進(jìn)去扎即;
-
父組件將方法的引用傳遞給子組件吞获,其中况凉,
getMsg
是父組件中methods
中定義的方法名稱,func
是子組件調(diào)用傳遞過(guò)來(lái)方法時(shí)候的方法名稱<son @func="getMsg"></son>
-
子組件內(nèi)部通過(guò)
this.$emit('方法名', 要傳遞的數(shù)據(jù))
方式各拷,來(lái)調(diào)用父組件中的方法刁绒,同時(shí)把數(shù)據(jù)傳遞給父組件使用<div id="app"> <!-- 引用父組件 --> <son @func="getMsg"></son> <!-- 組件模板定義 --> <script type="x-template" id="son"> <div> <input type="button" value="向父組件傳值" @click="sendMsg" /> </div> </script> </div> <script> // 子組件的定義方式 Vue.component('son', { template: '#son', // 組件模板Id methods: { sendMsg() { // 按鈕的點(diǎn)擊事件 this.$emit('func', 'OK'); // 調(diào)用父組件傳遞過(guò)來(lái)的方法,同時(shí)把數(shù)據(jù)傳遞出去 } } }); // 創(chuàng)建 Vue 實(shí)例烤黍,得到 ViewModel var vm = new Vue({ el: '#app', data: {}, methods: { getMsg(val){ // 子組件中知市,通過(guò) this.$emit() 實(shí)際調(diào)用的方法,在此進(jìn)行定義 alert(val); } } }); </script>
評(píng)論列表案例
目標(biāo):主要練習(xí)父子組件之間傳值
使用 this.$refs
來(lái)獲取DOM元素和組件引用
<div id="app">
<div>
<input type="button" value="獲取元素內(nèi)容" @click="getElement" />
<!-- 使用 ref 獲取元素 -->
<h1 ref="myh1">這是一個(gè)大大的H1</h1>
<hr>
<!-- 使用 ref 獲取子組件 -->
<my-com ref="mycom"></my-com>
</div>
</div>
<script>
Vue.component('my-com', {
template: '<h5>這是一個(gè)子組件</h5>',
data() {
return {
name: '子組件'
}
}
});
// 創(chuàng)建 Vue 實(shí)例速蕊,得到 ViewModel
var vm = new Vue({
el: '#app',
data: {},
methods: {
getElement() {
// 通過(guò) this.$refs 來(lái)獲取元素
console.log(this.$refs.myh1.innerText);
// 通過(guò) this.$refs 來(lái)獲取組件的數(shù)據(jù)和方法
console.log(this.$refs.mycom.name);
}
}
});
</script>