Vue组件
组件化思想:把页面拆分成多个功能块,每个功能块完成对应的功能,使整个页面便于维护和管理。
组件化提供了一种抽象,让我们开发出一个个独立可复用的小组件来构造应用。
任何的应用都会被抽象成一棵组件树。
Vue实例可看成一个root组件,即最大的父组件
尽可能地把页面拆分成一个个小的,可复用、可移植的组件。
这样可以使我们的代码方便组织和管理,并且拓展性也更强。
组件使用三步骤:
①创建组件构造器:调用extend()方法
②注册组件:Vue.component(‘组件标签名’,组件构造器)
③使用组件
全局组件
全局组件可以在多个Vue实例中使用,Vue.component()方法
<div id="app">
<my-cpn></my-cpn>
</div>
<script>
//创建组件的构造器对象
const cpnC = Vue.extend({
template:'<p>这是一个组件内容</p>'
})
//注册组件,参数为组件标签名和组件构造器
Vue.component('my-cpn',cpnC)
//创建一个Vue实例
new Vue({
el:'#app'
})
</script>
局部组件
在Vue实例下挂载components属性的组件为局部组件
<div id="app">
//显示
<my-cpn></my-cpn>
</div>
<div id="app2">
//不显示
<my-cpn></my-cpn>
</div>
<script>
//创建组件的构造器对象
var cpnC = {
template:'<p>这是一个组件内容</p>'
}
//注册组件,参数为组件标签名和组件构造器
new Vue({
el:'#app',
components:{
//组件标签名:组件构造器
'my-cpn':cpnC
}
})
new Vue({
el:'#app2'
})
</script>
在开发中一般使用局部组件较多。
且开发中一般只创建一个Vue实例
语法糖写法
优点:省去Vue.extend()写法,直接用一个对象代替,该对象内部还是调用了extend,Vue2.X的官网推荐语法糖写法,开发中用得更多的也是语法糖形式
1.全局组件的语法糖写法
<div id="app">
<cpn1></cpn1>
</div>
<script>
//直接用Vue.component注册组件
Vue.component('cpn1',{
template:`
<div>
<p>语法糖写法</p>
</div>
`
})
new Vue({
el:'#app',
})
</script>
2.局部组件的语法糖写法
<div id="app">
<cpn2></cpn2>
</div>
new Vue({
el:'#app',
components:{
cpn2:{
template:`
<div>
<p>局部组件的语法糖写法</p>
</div>`
}
}
})
组件模板抽离写法
1.script标签写法,注意标签的type必须是text/x-template
2.直接使用template标签
//第一种写法
<script type="text/x-template" id="cpn">
<div>
<p>我是使用script标签的分离式写法</p>
</div>
</script>
<!--第二种写法-->
<template id="cpn">
<div>
<p>我是直接使用template标签的分离式写法</p>
</div>
</template>
组件对象的data属性必须是函数,该函数必须有返回值,返回的对象内部保存数据
为了使组件里的内容可变,我们需要把它设置成变量形式。但组件内部不可以访问Vue实例里的变量,所以在注册组件时,就要在data属性中存放组件自己的变量数据。
<div id="app">
<cpn2></cpn2>
<cpn2></cpn2>
</div>
<template id="cpn">
<div>
<h3>当前计数:{{counter}}</h3>
<button @click="decrement">-</button>
<button @click="increment">+</button>
</div>
</template>
Vue.component('cpn2',{
template:'#cpn',
data:function(){
//return obj
return{
counter:0
}
},
methods:{
decrement(){
this.counter--
},
increment(){
this.counter++
}
}
})
父组件和子组件
当一个组件在另一个组件中祖册,被注册的组件是子组件,包含着子组件的是父组件,根组件是最大的父组件
<div id="app">
<cpn2></cpn2>
</div>
<script>
//创建子组件的构造器
var cpnC1 = Vue.extend({
template:'<p>这是子组件的内容</p>',
})
//创建父组件构造器
var cpnC2 = Vue.extend({
template:`
<div>
<p>这是父组件的内容</p>
<cpn1></cpn1>
</div>
`,
//在父组件构造器里注册组件,以便在构造器里使用
components:{
cpn1:cpnC1
}
})
new Vue({
el:'#app',
//在Vue实例里注册父组件
components:{
cpn2:cpnC2
}
})
</script>
父子组件传值
当页面存在父子组件时,一般由父组件向服务器发送请求,父组件再把请求数据传递给子组件,再由子组件展示数据。
列表的请求是统一的,不可能由列表项单独向服务器发送网络请求。
1.父组件向子组件传值 props(properties属性)
2.子组件向父组件传值 自定义事件
props
<div id="app">
<cpn v-bind:stars_="stars" :message_="message"></cpn>
</div>
<template id="cpn">
<div>
<ul>
<!-- 通过li和v-for属性遍历数组 -->
<li v-for="item in stars_">{{item}}</li>
</ul>
<p>{{message_}}</p>
</div>
</template>
//父传子props
var cpn = {
template:'#cpn',
props:['stars_','message_'],
data() {
return {}
}
}
new Vue({
el:'#app',
data:{
stars:['胡歌','陈伟霆','李荣浩'],
message:'太帅啦!'
},
components:{
cpn
}
})
2.自定义事件
子组件发生事件,通过$emit()触发事件,传递给父组件,
父组件通过v-on监听子组件事件,向服务器发送对应的请求
<div id="box">
<p>父组件</p>
<aaa @myevent="handleEvent"></aaa>
</div>
Vue.component("aaa",{
template:`
<div>
child
1.在子组件上埋好一个事件,回调函数
<button @click="handleClick">click</button>
</div>
`,
methods:{
handleClick(){
// 2.通过emit触发这个事件,顺带的,往里面面传参数
this.$emit("myevent",1000)}
}
})
var vm = new Vue({
el:"#box",
methods:{
handleEvent(data){
console.log("等待组件传值",data)
}
}
})
插槽
1.插槽的基本使用:在组件里定义一个slot标签
2.插槽的默认值
3.多个值在组建中替换时,都作为替换元素
<div id="app">
<cpn><h3>三级标题</h3></cpn>
<cpn><p>段落</p></cpn>
<cpn></cpn>
</div>
<template id="cpn">
<div>
<h1>我是组件</h1>
<!-- 给组件预备插槽 -->
<slot><button>按钮</button></slot>
</div>
</template>
new Vue({
el:'#app',
components:{
cpn:{
template:'#cpn'
}
}
})
注意点
1.给组件构造器定义组件标签名时,标签名可以加单引号,也可以不加单引号,两者都是对象
2.组件的根元素只能有一个,且必须是div,可以是div标签包住其他标签
3.component和components