注册组件
三个步骤
①创建组件构造器Vue.extend()
传入template
②注册组件Vue.component()
需要传递两个参数:1.注册组件的标签名 2.组件构造器
③使用组件<my-cpn></my-cpn>
<div id="app">
<my-cpn></my-cpn>
<my-cpn></my-cpn>
<my-cpn></my-cpn>
</div>
<script src="js/vue.js"></script>
<script>
const cpnContent = Vue.extend({
template:`
<div>
<h2>我是标题</h2>
<p>我是内容,哈哈哈哈</p>
<p>我是内容,呵呵呵呵</p>
</div>`
})
Vue.component('my-cpn',cpnContent) //参数:标签名,组件构造器
var app = new Vue({
el:'#app',
data:{
}
})
</script>
全局组件和局部组件
<div id="app">
<cpn></cpn>
<cpn></cpn>
<cpn></cpn>
</div>
<div id="app1">
<cpn></cpn>
</div>
<script src="js/vue.js"></script>
<script>
const cpnContent = Vue.extend({
template:`
<div>
<h2 class="tit">我是标题</h2>
<p>我是内容,哈哈哈哈</p>
<p>我是内容,呵呵呵呵</p>
</div>`
})
//Vue.component('cpn', cpnContent) 全局组件
const app = new Vue({
el:'#app',
components:{//局部组件
cpn: cpnContent //在全局组件时候用的标签名字my-con有-,局部的标签有-就会报错
}
})
const app1 = new Vue({
el:'#app1'
})
</script>
父组件和子组件
<div id="app">
<cpn2></cpn2>
<!-- <cpn1></cpn1> 如果要显示这个需要在全局组件中注册,在父组件中注册是局部组件,他的作用域只能在父组件中显示-->
</div>
<script src="js/vue.js"></script>
<script>
//创建第一个组件构造器(子组件)
const cpnCon1 = Vue.extend({
template: `
<div>
<h2>我是标题1</h2>
<p>我是内容,哈哈哈</p>
</div>
`
})
//创建第二个组件构造器(父组件)
const cpnCon2 = Vue.extend({
template: `
<div>
<h2>我是标题2</h2>
<p>我是内容,呵呵呵</p>
<cpn1></cpn1>
</div>
`,
components: { //注册组件1,组件2里面嵌套了组件1
cpn1: cpnCon1
}
})
//root 根组件
var app = new Vue({
el:'#app',
data:{
message:'hello'
},
components:{ //注册局部组件
// cpn1: cpnCon1,
cpn2: cpnCon2 //注册组件2
}
})
</script>
注册组件语法糖
<div id="app">
<cpn1></cpn1>
<cpn2></cpn2>
</div>
<script src="js/vue.js"></script>
<script>
//创建组件构造器
//const cpnCon = Vue.extend()
//2.注册全局组件(可省略第一步,直接注册组件) component不用加s
Vue.component('cpn1',{
template: `
<div>
<h2>我是标题全局组件</h2>
<p>我是内容,哈哈哈</p>
</div>`
})
var app = new Vue({
el:'#app',
data:{
message:'hello'
},
components:{//component要加s 这里是注册局部组件
'cpn2':{
template: `
<div>
<h2>我是标题局部组件</h2>
<p>我是内容,哈哈哈</p>
</div>`
}
}
})
</script>
模板的分离写法
使用标签,添加id
Vue.component('cpn',{
template: `#cpn`
})
组件数据的存放
组件对象也有一个data属性,只是这个data属性必须是一个函数,为什么必须是函数呢?
原因是在于Vue让每个组件对象都返回一个新的对象,因为如果是同一个对象的,组件在多次使用后会相互影响
<div id="app">
<cpn></cpn>
</div>
<template id="cpn">
<div>
<h2>{{title}}</h2>
<p>我是内容</p>
</div>
</template>
<script src="js/vue.js"></script>
<script>
Vue.component('cpn',{
template: `#cpn`,
data(){ //data属性必须是函数
return { //函数必须返回一个对象
title:'我是标题哦'
}
}
})
var app = new Vue({
el:'#app',
data:{}
})
</script>
父子组件的通信
- 通过props向子组件传递数据
注意一:驼峰命名会报错,可以在组件上面把大写I改成-i(:cInfo写成:c-info)
注意二:子组件中的模板中必须要在最外层写上根元素,就是大的div
props的值有两种方式
方式一:字符串数组,数组中的字符串就是传递时的名称
方式二:对象,对象可以设置传递时的类型,也可以设置默认值等
步骤
步骤一:在父组件中写好数据movies: ['我是父组件的数据1','我是父组件的数据2']
步骤二:(已知)组件上可以写自定义属性,在子组件中定义props(可以是数组也可以是对象)属性(可以传多个属性)接收即可,props里面写变量名称props: ['childmovies']
步骤三:在引用的子组件<cpn/>
上面通过v-bind绑定把父组件的值传递给子组件的变量名<cpn :childmovies='movies'/>
<div id="app">
<!--父组件movies的数据赋值给子组件props的childmovies-->
<cpn :childmovies="movies" :childmessage="message"></cpn>
</div>
<template id="cpn">
<ul>
<li v-for="item in childmovies" :key="item">{{ item }}</li>
</ul>
<!--<h3>{{ childmovies }}</h3>-->
<p>{{childmessage}} </p>
</template>
<script src="js/vue.js"></script>
<script>
//相当于子组件
const cpn = {
template:`#cpn`,
props:['childmovies','childmessage'] //childmovies相当于变量
}
//相当于父组件
const app = new Vue({
el:'#app',
data:{
movies: ['海王','海贼王','海尔兄弟'],
message: 'hello'
},
components: {
cpn //对象增强写法,原来的写法是'cpn': cpn(标签名,组件构造器)
}
})
</script>
//除了数组之外,我们也可以使用对象,当需要对props进行类型等验证时,就需要对象写法了。
props: {
//1.类型限制
//childmovies: Number
//2.提供一些默认值
/*childmessage: {
type: String,
default: 'aaa', //写了默认值之后,子组件的标签上可以不写v-bind绑定自定义属性传值了
required: true //必须加上childmovies这个属性
}, */
//3.类型是对象或者数组时,默认值必须是一个函数
childmovies: {
type: String,
default() {
return {}
}
}
}
- 通过事件向父组件发送消息
$.emit
<!--父组件模板-->
<div id="app">
<!-- 通过v-on接收子组件的事件监听发送, itemclick不能写驼峰 -->
<cpn @itemclick="cpnCilck"></cpn>
</div>
<!--子组件模板-->
<template id="cpn">
<div>
<button v-for="item in cate" @click="btnClick(item)">{{item.name}}</button>
</div>
</template>
<script src="js/vue.js"></script>
<script>
//子组件
const cpn = {
template:`#cpn`,
data(){
return {
cate:[
{id:'aaa', name:'热门推荐'},
{id:'bbb', name:'手机数码'},
{id:'ccc', name:'家用家电'},
{id:'ddd', name:'电脑办公'}
]
}
},
methods:{
btnClick(item){
//通过emit把子组件的item传给父组件,itemClick是事件名字,自定义事件
this.$emit('itemclick', item)
}
}
}
//父组件
const app = new Vue({
el:'#app',
data:{
message:'hello'
},
components:{
cpn
},
methods:{
cpnCilck(item){
console.log('cpnCilck',item);
}
}
})
</script>
父子组件的访问方式
父组件访问子组件: $children 或 $refs
子组件访问父组件: $parent
插槽
- 插槽的基本使用
在template中添加<solt></solt>
- 插槽的默认值
<solt><button></button></solt>
- 具名插槽
<cpn><span name='center'>标题</span></cpn>
<solt name='center'><span>中间</span>/solt>
- 编译作用域
父组件模板的所有东西都会在父级作用域内编译;子组件模板的所有东西都会在子级作用域内编译。
isShow使用的是Vue实例中的属性 - 作用域插槽
v-slot