组件的使用分成三部分:
<body>
<div id="app">
<!--3.使用组件,组件名称,必须小写-->
<my-cpn></my-cpn>
</div>
</body>
<script src="../vue.js"></script>
<script>
//ES6可以使用``来代替单引号,它是模板字符串,可以换行,表示一个字符串,
//如`abc`
//1.创建组件构造器对象
const cpn = Vue.extend({
template: `
我是组件
`
})
//2. 注册全局组件,该组件可以在多个Vue对象实例下使用
Vue.component("my-cpn",cpn);
//2.注册局部组件,开发时,使用最多的时局部组件
const app = new Vue({
el: '#app',
components:{
my-cpn:cpn
}
})
</script>
父组件和子组件的创建,组件和组件之间存在层级关系,
<body>
<div id="app">
<cpn2></cpn2>
</div>
</body>
<script src="../vue.js"></script>
<script>
//创建子组件
const cpn1=Vue.extend({
template:`
我是子组件
`
})
//创建父组件
const cpn2 = Vue.extend({
template:`
我是父组件
`,
components:{
cpn1:cpn1
}
})
const app = new Vue({
el:'#app',
components:{
cpn2:cpn2
}
})
</script>
组件的语法糖注册方式
Vue.component('cpn1',{
template:`我是语法糖创建的全局组件`,
components:{
}
})
const app = new Vue({
el:'#app',
components:{
'cpn1':{
template:`我是语法糖创建的局部组件`
}
}
})
组件模板抽离
标签<body>
<div id="app">
<cpn1></cpn1>
</div>
<!--模板,注意type的值-->
<script type="text/x-template" id="cpn1">
<div>{{title}}</div>
</script>
</body>
<script src="../vue.js"></script>
<script>
//注册全局组件
Vue.component('cpn1', {
template: '#cpn1',
data(){
return {
title:'我是标题'
}
}
})
const app = new Vue({
el: '#app'
})
</script>
标签<template id="cpn1">
<div>我是template标签创建的模板</div>
</template>
1.组件内部是不可以访问Vue实例里面的data的数据,组件中的data属性必须是函数
2.Vue组件应该有自己保存数据的地方
Vue.component('cpn1', {
template: '#cpn1',
data() {
//返回一个对象
return {
title:'我是标题'
}
},
})
Vue官网提到,可以通过props向子组件传递数据。通过事件向父组件发送消息
props的基本用法
在组件中,使用选项props来声明需要从父级接收到的数据
props的值有两种方式:
//父组件向子组件通信-使用数组的方式
<body>
<div id="app">
<cpn1 :message='message' :movies='movies'></cpn1>
</div>
</body>
<template id="cpn1">
<div>
<div>{{message}}</div>
<div>{{movies}}</div>
</div>
</template>
<script src="../vue.js"></script>
<script>
const cpn1 = {
template: '#cpn1',
props: ['message', 'movies'],
data() {
return {}
},
}
const app = new Vue({
el: '#app',
data: {
message: 'Hello',
movies: ['a', 'b', 'c', 'd']
},
components: {
cpn1
}
})
</script>
//建议通过对象申明属性
const cpn={
template:'#cpn1',
props:{
//添加默认值
message:{
type:String,
default:'',
//default的另一种写法
default(){
return ''
}
//表示该属性必传
required:true,
},
movies:Array
}
}
注意:props不支持使用驼峰命名法,如果有多个关键子,在html中需要用" -" 来连接,在js中可以使用驼峰
<body>
<div id="app">
<cpn1 @itemclick='fatherMethod'></cpn1>
</div>
</body>
<template id="cpn1">
<div>
<button v-for='item in categories'
@click='btnclick(item)'>
{{item.name}}
</button>
</div>
</template>
<script src='../vue.js'></script>
<script>
//1.子组件
const cpn1 ={
template:'#cpn1',
data() {
return {
categories:[
{id:1,name:'推荐'},
{id:2,name:'数码'},
{id:3,name:'家电'},
{id:4,name:'办公'},
]
}
},
methods: {
btnclick(item){
this.$emit('itemclick',item);
}
},
}
//app为父组件
const app =new Vue({
el:'#app',
components:{
cpn1
},
methods: {
fatherMethod(item){
console.log(item)
}
},
})
</script>
组件中 watch 用于监听组件中属性的改变
props:{
number1:Number,
number2:Number
}
watch:{
number1(newValue){
//监听number1的属性值的变化
},
number2(){
//监听number2的属性值变化
}
}
$children
或者 $refs
$parent
this.$children
是一个数组类型,它包含了所有的子组件对象,对象的类型是VueComponent
比较推推荐使用$refs
来访父组件中的子组件,
<cpn ref='aaa'></cpn>
//父组件的js的方法,页面访问
method:{
btnClick(){
console.log(this.$refs.aaa)
}
}
子组件访问父组件
this.$parent
来获取,this.$root.message
插槽的作用是为了让使用者决定组件内部需要展示的内容是什么。
插槽的基本使用
<body>
<div id="app">
<cpn><button>按钮</button></cpn>
</div>
</body>
<template id="cpn">
<div>
我是组件
<!--插槽-->
<slot>
<!--默认插槽的标签元素-->
<button>默认按钮</button>
</slot>
</div>
</template>
<script src="../vue.js"></script>
<script>
const cpn = {
template: '#cpn'
}
const app = new Vue({
el: '#app',
components: {
cpn
}
})
</script>
在组件中有多个slot 插槽标签,需要给具体的插槽不同的名称,来指定插入的位置。
<body>
<div id="app">
<cpn>
<span slot="left">我是左边的标签</span>
<span slot="center">我是中间的标签</span>
<span slot="right">我是右边的标签</span>
</cpn>
</div>
</body>
<template id="cpn">
<div>
我是组件
<slot name='left'><button>默认按钮</button></slot>
<slot name='center'></slot>
<slot name='right'></slot>
</div>
</template>
<script src="../vue.js"></script>
<script>
const cpn = {
template: '#cpn'
}
const app = new Vue({
el: '#app',
components: {
cpn
}
})
</script>
编译作用域:父组件模板的所有东西都会在父级作用域内编译;子组件模板的所有东西都会在子级作用域内编译
父组件替换插槽的标签,但是内容由子组件来提供。数据内容在子组件,但是希望父组件告诉子组件应该如何展示,此时利用solt作用域插槽就可以了。
<body>
<div id="app">
<!--写法1-->
<cpn></cpn>
<cpn>
<!--2.5.x , 写法二-->
<template slot-scope='slot'>
<span v-for='item in slot'>
{{item}}
</span>
</template>
</cpn>
<!--写法三-->
<cpn>
<template slot-scope='slot'>
<span>{{slot.data.join('-')}}</span>
</template>
</cpn>
</div>
</body>
<template id="cpn">
<div>
<slot :data='language'>
<ul>
<li v-for="item in language">{{item}}</li>
</ul>
</slot>
</div>
</template>
<script src="../vue.js"></script>
<script>
const cpn = {
template: '#cpn',
data() {
return {
language: ['java', 'javaScript', 'C++', 'C#', 'python', 'Go', 'Swift']
}
},
}
const app = new Vue({
el: '#app',
components: {
cpn
}
})
</script>