一、 组件
- 使用Vue.extend({template:``}) 构造组件
const myCpn1= Vue.extend({
template:`
<h2>this is component1</h2>
`
})
- 注册组件Vue.component(“使用时的名称”,“构造的组件名”),使用该方法构造的组件为全局组件
Vue.component("my-cpn",myCpn)
- 在生成的Vue对象的components属性中注册的组件为局部组件,注意components为复数
let app = new Vue({
el: "#app",
components:{
my_cpn:myCpn,
}
})
- 组件的注册还可以在另一个组件的components属性中进行,注册后成为该组件的子组件,注意子组件只能在父组件内部使用,如果还需要在父组件外部使用,那就还得在Vue对象中再次注册
const myCpn1= Vue.extend({
template:`
<h2>this is component1</h2>
`
})
const myCpn2=Vue.extend({
template:`
<div>
<h2>this is in component2</h2>
<mycpn1></mycpn1> //mycpn1在组件mycpn2内部进行了注册,成了mycpn2的子组件
</div>
`,
components:{
mycpn1:myCpn1,
}
})
- 使用组件
<div id="app">
<mycpn2></mycpn2>
<mycpn1></mycpn1>
</div>
二、组件语法糖写法
语法糖写法,系统在内部会自动调用Vue.extend()函数去处理1. **构造并注册**全局组件
Vue.component("mycpn1",{
template:`
<h1>hello world</h1>
`
})
- 局部组件
let app = new Vue({
el: "#app",
components:{
mycpn2:{
template:'<h1>语法糖局部注册</h1>'
}
}
})
- 构造并并注册子组件的方法和上面类似,不再赘述
三. 模板分离写法
可以看出,到目前为止所有的模板的HTML标签均写在javascript里面,看起来比较乱,所以Vue提供了两种模板分离的写法- script标签
<script type="text/x-template" id="mycpn2"> //此处要注意到的是script标签的类型
<h1>模板分离</h1>
</script>
<script>
let app = new Vue({
el: "#app",
components:{
mycpn2:{
template:"#mycpn2" //通过id将模板和对应的内容联系起来
}
}
})
</script>
- template标签
<template id="mycpn2_tmp">
<h2>模板分离2</h2>
</template>
<script>
let app = new Vue({
el: "#app",
components:{
mycpn2:{
template:"#mycpn2_tmp"
}
}
})
</script>
四、组件使用的数据
组件使用的数据必须用data函数来返回,利用的是函数的作用域,防止多次调用组件时数据交互之间产生干扰。let app = new Vue({
el: "#app",
components:{
mycpn2:{
template:"#mycpn2_tmp",
data(){
return {
message:"hello, world"
}
}
}
}
})
五、父子组件数据通信
- 父===>子 props,通过在组件内部定义props属性
<div id="app">
<mycpn1 :cmovies="movies" :cmessage="message"></mycpn1> //组件的使用
</div>
<template id="cpn"> //注意在template中只能从一个根标签出发,这里如果我将div去掉直接让ul和h2同级出现会报错
<div>
<ul>
<li v-for="item in cmovies">{{item}}</li>
</ul>
<h2>hello</h2>
</div>
</template>
<script src="../static/vue.js"></script>
<script>
let app = new Vue({
el: "#app",
data:{
movies:["鬼吹灯","阿凡达","快乐星球"],
message:"hello, world"
},
components:{
mycpn1:{
template:"#cpn",
props:["cmovies","cmessage"] //poros属性传递来自父组件的数据,这里是数组写法,还有更常用的对象写法
}
}
})
</script>
对象写法1
props:{
cmovies:Array,
message:String,
}
对象写法2
props:{
cmovies:{
type:Array,
default(){ //需要注意的是,如果数据的类型为对象或者是数组时,默认值要以范湖的形式返回
return ["Null"]
}
},
cmessage:{
type:String,
default:"chenchen"
},
}
大坑注意:在组件的使用过程中,子组件和父组件传递时是不支持驼峰标识的,需要进行转换
<mycpn1 :c-movies="movies" :cmessage="message"></mycpn1> //在使用时,cMovies==>c-movies
props:{
cMovies:{
type:Array,
default(){
return ["Null"]
}
},
}
六、子组件到父组件的数据通信(一般为事件)
大致过程可以总结为:a. 在子组件内部监听事件 b. 在methods中处理监听到的事件 c. methods中处理事情时,向父组件发射一个约定好的事件 d. 在父组件中会一直监听这个事件,一旦事件被触发,会交给自己的methods去处理
实例代码
<div id="app">
<cpn :categories="categories" @btnclick="handleClick"></cpn> //在父组件中监听btnclick事件,然后交给自己的handleClick函数去处理
</div>
<template id="cpn">
<div>
<button v-for="item in categories" @click="btnClick(item)">{{item}}</button> //子组件监听click事件,然后交给自己btnClick()函数处理
</div>
</template>
<script src="../static/vue.js"></script>
<script>
const cpn={
template:"#cpn",
props:{
categories:{
default() {
return [];
},
}
},
data(){
return {
message:"hello"
}
},
methods:{
btnClick(item){
this.$emit("btnclick",item) //子组件处理click事件时没有做别的操作,只是触发了父组件一直在监听的事件
},
}
}
const app= new Vue({
el:"#app",
data:{
categories:["服装","家电","数码相机","图书","出行"],
},
components:{
cpn
},
methods:{
handleClick(item){
console.log(item);
}
}
})
</script>