-
组件的使用分成三个步骤:
1.创建组件构造器:Vue.extend() ,使用template
2.注册组件:Vue.component(),需要传递两个参数:- 注册组件的标签名
- Vue.extend() 返回的构造器
3.使用组件 :在Vue实例的作用范围内使用,即必须挂载在某个Vue实例下
-
全局组件 :可以在任意一个Vue实例中使用
-
局部组件(常用,一般开发只有一个Vue实例):如何注册?在vue实例的components属性中注册
-
父子组件
组件cpnC1在cpnC2中,(为了在cpnC2中使用cpnC1),cpnC2在Vue实例中注册,但是cpnC1不能在Vue实例中使用,要使用的话得在Vue实例的components中添加cpn1:cpnC1
<div id="app">
<cpn></cpn>
<cpn></cpn>
</div>
<script>
const cpnC1 = Vue.extend({
template:`
<div>
<h2>我是组件1</h2>
</div>
`
});
const cpnC2 = Vue.extend({
template:`
<div>
<h2>我是组件2</h2>
<cpn1></cpn1>
</div>
`,
components:{
cpn1:cpnC1,
}
});
const app = new Vue({
el:"#app",
data:{
},
components:{
cpn:cpnC2,
}
});
</script>
-注册全局组件语法糖,省略了Vue.extend()
// 注册全局组件,标签名:cpn-parent
Vue.component("cpn-parent",{
template:`
<div>
<h2>I'm cpn-parent</h2>
<cpnChild2></cpnChild2>
</div>
`,
//子组件
components:{
cpnChild2:{
template:`
<div>
<h3>I'am child</h3>
</div>
`
}
}
})
// 注册全局组件,标签名:cpn-child
Vue.component("cpn-child",{
template:`
<div>
<h3>I'am cpn-child</h3>
</div>
`
})
- 注册局部组件语法糖
//注册局部组件语法糖,省略了Vue.extend()
const app = new Vue({
el:"#app",
data:{
},
components:{
cpn1:{
template:`
<div>
<h2>我是标题1</h2>
<p>我是内容</p>
</div>
`}
}
});
- 模板抽离:
<template id="cpn">
<div>
<h2>我是组件</h2>
</div>
</template>
<script>
Vue.component('cpn1',{
template:'#cpn',
})
-
组件中不能直接访问Vue实例中的data,而且即使可以访问,如果将所有的数据都放在Vue实例中,Vue实例就会变得非常臃肿,
-
结论:Vue组件应该有自己保存数据的地方
-
组件中的data是一个函数,并返回一个对象,对象内部保存着数据
data:function(){
return{
title:'我是组件title',
}
}
//简写为:
data(){
return{
title:'我是组件title',
}
}
- 组件的data是一个函数,每个组件返回对象都不同,保持不同组件有各自的状态
<!DOCTYPE html>
<html>
<head>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
</head>
<body>
<div id="app">
<counter></counter>
<counter></counter>
<counter></counter>
</div>
<template id="counter">
<div>
<h2>当前计数:{{count}}</h2>
<button @click="incr">+</button> <button @click="decr">-</button>
</div>
</template>
<script>
const count = {
count:0,
}
Vue.component('counter',{
template:'#counter',
//每个组件调用data函数,返回各自的count,与其他组件的对象不同
data(){
return{
count:0,
}
},
//return一个已经定义好的对象count时,所有组件共享count
// data(){
// return count;
// },
methods:{
incr(){
this.count++;
},
decr(){
this.count--;
}
}
})
const app = new Vue({
el:"#app",
data:{
},
})
</script>
</body>
</html>
-
如何进行父子组件间的通信:
1.父组件通过props向子组件传递数据
2.子组件通过自定义事件$emit Events向父组件发送消息 -
对象增强写法:
const name = 'why';
const obj = {
name:name,
}
//简写为:
const obj = {
//key:name,value:name的值
name,
}
- props 的值有两种方式:
1.字符串数组,数组中的字符串就是传递时的名称
2.对象,对象可以设置传递时的类型,也可以设置默认值等 - 父组件向子组件传递数据
<!DOCTYPE html>
<html>
<head>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
</head>
<body>
<div id="app">
<!-- 如果没用v-bind,即没有冒号,movies当做字符串而不是变量传给childmovies-->
<cpn :childmovies="movies" :childmessage="message" ></cpn>
</div>
<template id="child">
<div>
<ul>
<li v-for="item in childmovies">{{item}}</li>
</ul>
<h3>{{childmessage}}</h3>
</div>
</template>
<script>
//app实例的子组件
const cpn = {
template:"#child",
// props的数组写法
// props:['childmovies','childmessage'],
// props的对象写法
props:{
//1,对传入类型限制
// childmovies:Array,
// childmessage:String,
// 2.当没有传值时,赋予默认值
childmovies:{
type:Array,
//类型是Array/Object时,默认值必须是一个函数
default(){
return ['默认电影1','默认电影2'];
}
},
childmessage:{
type:String,
default:'哈哈哈',
//必须传值
required:true,
},
},
data(){
return{}
},
methods:{},
}
const app = new Vue({
el:"#app",
data:{
movies:['海王','海贼王','海尔兄弟'],
message:'hello aaa~',
},
components:{
//对象增强写法,相当于cpn:cpn
cpn,
}
})
</script>
</body>
</html>
- 在props中的属性使用驼峰,然后在v-bind里写成以-连接的方式,
- template里面包含很多标签时,要确保有一个root element,就是给最外面加个div标签啦