Vue组件,扩展html,封装可重用的代码
组件命名方式有两种
(1)短横线分隔命名,如 'b-box'
(2)PascalCase首字母大写命名即大驼峰,但是当使用 PascalCase 定义组件时,在html文档里引用时必须使用kebab-case短横线分隔命名才生效,否则报错,如'TableBox'要写成'table-box'
原因:因为HTML对大小写不敏感,JS对大小写敏感
组件里的data属性必须是一个函数
1.局部组件
在Vue实例中,创建一个components对象,里面定义组件名称,一些数据方法等,先定义一个组件名称,template里写的是可重用的HTML模板,props里定义的是一些静态属性
components: {
'b-box': {
template: `<div class="box">
<h2 class="title">{{title}}</h2>
<p class="content">{{content}}</p>
</div>`,
props: ['title', 'content']
}
}
当要使用这个模板时,标签就是要使用的组件名,在Vue实例中,挂载对象,定义相关的数据,然后组件就可绑定这些数据,渲染页面
<div id="app">
<b-box v-for="(item,index) in list" :key="index"
:title="item.title" :content="item.content"></b-box>
</div>
注意:局部组件只能在当前Vue实例作用域下有效
2.全局组件
全局组件必须写在Vue实例创建之前,才在该根元素下面生效;
Vue.component:(
'b-count', {
template: `<div class="content" >
<span>{{types}}</span>
<div>
<button @click="MyCount--" :disabled="MyCount===1">-</button>
<input type="text" :value="MyCount">
<button @click="MyCount++" :disabled="MyCount===10">+</button>
</div>
</div>`,
})
组件间的数据传递
子组件通过$emit可以触发事件,第一个参数为要触发的事件,第二个事件为要传递的数据
在组件中来监听MyCount值的变化
watch: {
MyCount(val) {
console.log(val);
this.$emit('synccount', val)
}
}
在Vue实例中接收MyCount值的变化
methods: {
synccount(index, e) {
this.list[index].count = e
}
}
在模板中点击触发事件
<b-count v-for="(item,index) in list" :key="index" :types="item.types" :count="item.count"
@synccount="synccount(index,$event)">
</b-count>
3.父子组件
$parent是获取父组件对象
$root是获取根组件对象
$children是获取子组件对象
$ref返回的是一个对象,对象中包含所有带有ref属性的组件
父组件
ue.component('b-tabs', {
template:`
<div class="tabs">
<ul class="title">
<li @click="activeIndex=index" :class="{active:activeIndex===index}" v-for="(item,index) in titles" :key="index">{{item}}</li>
</ul>
<ul class="content">
<slot></slot>
</ul>
</div>
`,
data() {
return {
//高亮索引
activeIndex:0,
//定义titles数组
titles:[]
}
},
watch:{
//监听高亮索引
activeIndex(val){
//先隐藏所有的子组件
this.$children.forEach(c=>c.isShow=false)
//再显示当前高度的子组件
this.$children[val].isShow = true
}
},
// 父组件挂载完成时,所有的子组件一定全部都挂载完成了
mounted() {
this.$children[this.activeIndex].isShow = true
},
})
子组件
Vue.component('b-tabs-item', {
props:['title'],
template:`
<li v-show="isShow">
<slot></slot>
</li>
`,
data() {
return {
//是否显示
isShow:false
}
},
created() {
// 在子组件的created生命周期函数中,可以获取到父组件的数据
this.$parent.titles.push(this.title)
},
})
模板运用
<div id="app">
<b-tabs>
<b-tabs-item title="南京">
<li>南京的盐水鸭真好吃</li>
</b-tabs-item>
<b-tabs-item title="北京">
<ul>
<li>北京的烤鸭真好吃</li>
</ul>
</b-tabs-item>
<b-tabs-item title="无锡">
<a href="#">无锡的小笼包真好吃</a>
</b-tabs-item>
</b-tabs>
</div>
运行截图

插槽问题
用<slot></slot>来表示,相当于一个占位符,父组件可以在这个占位符中填充任何模板代码,如 HTML、组件等,填充内容会替换子组件的<slot></slot>标签。如果子组件没有使用插槽,父组件如果需要往子组件中填充模板或者html, 是没法做到的。
4.第三方组件库
如element-ui,vant,iview等,在需要使用的页面中引入其样式及文件,就可以使用了,简单又高效