一、Vue組件
概念:html
、css
與js
的集合體,為該集合體命名,用該名字復用html
、css
與js
組成的集合體 => 復用性
1. 組件分類
1.1 根組件
根組件:new vue()生成的組件。
new Vue({
el: 'section',
data: {},
methods: {},
});
1.2 局部組件
局部組件:組件名 = {}, {}內部采用的是vue的語法。定義后需要在根組件中注冊。
let myTag = {
template: `
<div>
<h1>我是局部組件</h1>
</div>
`
};
new Vue({
el: 'section',
data: {},
methods: {},
components: {
myTag,
},
});
1.3 全局組件
全局組件:Vue.component('組件名',{}),{}內部采用的是vue語法。不需要在vue實例中注冊。
注意:全局組件必須寫在vue實例上方,不然渲染不出來。
Vue.component('my-tag2',{
template: `
<div>
<h1>我是局部組件</h1>
</div>
`
});
new Vue({
el: 'section',
data: {},
methods: {},
});
2. 組件的特點
1、組件都有管理自己HTML頁面結構的template實例成員。
- template對應的值才是vue實例真正要用的虛擬Dom。
- 掛載點掛載的標簽是真實的標簽。
- template只能有一個根標簽。
2、根組件是最頂層的父組件,局部與全局組件為子組件,也可以成為其他局部與全局組件的父組件。
3、子組件的數據需要隔離(數據組件化,每一個組件都擁有自己獨立的名稱空間)。
4、局部組件必須注冊后才能使用,全局組件不需要注冊,提倡使用局部組件。(局部組件不注冊就是一個普通對象)
5、組件中出現的所有變量(模板中、邏輯中),都由該組件自己提供管理。(子組件若有根組件,則子組件中的變量由根組件提供。)
6、局部全局和根組件都是一個vue實例,一個實例對應一套html、css、js結構,所以實例也是組件。
3. 如何創建組件
1、聲明組件
2、注冊組件(全局組件不需要注冊)
- component
3、渲染組件
let myTag = {
template: `
<div>
<h1>我是局部組件</h1>
</div>
`
};
Vue.component('my-tag2',{
template: `
<div>
<h1>我是局部組件</h1>
</div>
`
});
new Vue({
el: 'section',
data: {
msg:'組件'
},
methods: {},
components: {
myTag,
},
});
注意:
- el掛載的標簽會被實例中的template屬性對應的模板替換,所以不要在跟組件中設置template屬性。
<body>
<div id="app">
{{ msg2 }}
</div>
</body>
<script>
new Vue({
el: '#app',
data: {
msg: '組件信息',
msg2: '組件信息2'
},
template: '<p>{{ msg }}</p>',
})
</script>
</html>
總結:
- 根組件,可以不明確template,template默認采用掛載點頁面結構;如果設置了template,就會導致掛載點內部的內容無效,因為會被template替換。
4. 組件的數據局部化
局部或全局組件,每個組件可能會被復用多次,但是組件的樣式相同,不一定數據也相同,所以每個組件應該有自己獨立的變量名稱空間來記錄本組件的數據。
因此,將組件數據局部化的目的,是讓組件之間數據隔離。
做法:
- 將data寫成函數,返回本來data對應的字典,這樣就可以通過函數產生一個局部作用域來作為組件本身單獨的名稱空間。
<body>
<div id="app">
<div class="wrap">
<local-tag></local-tag>
<local-tag></local-tag>
<local-tag></local-tag>
<local-tag></local-tag>
</div>
</div>
</body>
<script>
let localTag = {
template: `
<div class="box" @click="fn">
<img src="img/001.jpg" alt="">
<h2>數了{{ count }}下</h2>
</div>
`,
data() {
return { // 產生名稱空間
count: 0,
}
},
methods: {
fn() {
console.log(this);
this.count++;
}
}
};
new Vue({
el: '#app',
data: {},
components: {
localTag,
}
});
</script>
5. 組件傳參·父傳子
有時候我們需要將父標簽中的一些數據傳給子標簽進行渲染,但是此時子標簽已經使用獨立的名稱空間了,該怎么做呢?
我們可以將父標簽中的數據作為變量值賦給子標簽的某個屬性,這樣就可以通過這個屬性來訪問屬性值了,而剛好這個屬性值就是我們需要的父標簽的數據。
那么什么屬性可以用來接收數據呢?
答案是自定義屬性。
1、子組件可以通過props自定義組件屬性(采用反射機制,需要填寫字符串,但是使用時可以直接作為變量)
2、將父組件的變量賦值給子組件的自定義屬性,就可以將該子組件的自定義屬性當做變量來使用。通過這個自定義屬性就可以訪問父標簽中的data數據了。
<body>
<section>
<my-tag :myprop="msg"></my-tag>
</section>
</body>
<script>
let myTag = {
props:['myprop',],
template: `
<div>
<h1>{{ myprop }}</h1>
</div>
`
};
new Vue({
el: 'section',
data: {
msg:'我是根標簽里面的msg'
},
methods: {},
components: {
myTag,
},
});
</script>
6. 組件傳參·子傳父
若是父標簽需要用到子標簽內部的data數據該怎么辦呢?
可以通過在子標簽內部使用this.$emit('自定義事件名', 觸發事件回調的參數們)
方法手動將標簽的自定義事件觸發。
此時子標簽的自定義事件對應的是父標簽的某個方法,this.$emit('自定義事件名', 觸發事件回調的參數們)
而這里面的參數則會從子標簽中彈出,傳入父標簽方法中由其接收。
<body>
<div id="app">
<h1>{{ h1 }}</h1>
<h3>{{ h3 }}</h3>
<tag @action="actionFn"></tag>
</div>
</body>
<script>
let tag = {
template: `
<div>
<input type="text" v-model="t1">
<input type="text" v-model="t2">
<button @click="changeTitle">修改標題</button>
</div>
`,
data() {
return {
t1: '',
t2: '',
}
},
methods: {
changeTitle() {
if (this.t1 && this.t2) {
this.$emit('action', this.t1, this.t2);
// 清空t1和t2
this.t1 = '';
this.t2 = '';
}
}
}
};
new Vue({
el: '#app',
data: {
h1: '主標題',
h3: '子標題'
},
components: {
tag2,
},
methods: {
actionFn(a, b) {
console.log('觸發了', a, b);
this.h1 = a;
this.h3 = b;
},
}
})
</script>