了解更多详情请访问 https://cn.vuejs.org/v2/guide/index.html
一、组件
组件是一种封装可复用的集合,通过组件化,将更好的完成繁杂的需求
组件化特点,具体如下:
1.拥有唯一性的组件名称,方便调用;
2.以组件名称为 HTML 元素标签形式存在,扩展了 HTML;
3.组件可以复用,且组件与组件之间互不干涉;Vue中使用组件的三大步骤:
1.定义组件(创建组件)
2.注册组件(分为全局注册和局部注册)
3.使用组件(写组件标签)
二、注册组件
局部注册:在实例选项中注册局部组件,这样组件只能在这个实例中使用
全局注册:所有实例都能用全局组件
<div id="root">
<!-- 第三步:编写组件标签 -->
<hello></hello>
<hr>
<h1>{{msg}}</h1>
<hr>
<!-- 第三步:编写组件标签 -->
<student ></student>
</div>
</body>
<script>
Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。
//第一步:创建student组件
const student = Vue.extend({
template:`
<div>
<h2>学生姓名:{{studentName}}</h2>
<h2>学生年龄:{{age}}</h2>
</div>
`,
data(){
return{
studentName:'张三',
age:18
}
}
})
//第一步:创建hello组件
const hello = Vue.extend({
template:`
<div>
<h2>你好啊!{{name}}</h2>
</div>
`,
data(){
return{
name:'Tom'
}
}
})
//第二步:全局注册组件
Vue.component('hello',hello)
//创建vm
new Vue({
el:'#root',
data:{
msg:'你好啊!'
},
//第二步,注册组件(局部组件)
components:{
student
}
})
</script>
注意:
1.
Vue.extend()
是一个基础构造器(全局 API),意图创建一个子类;2.
Vue.component()
是注册组件,参数 1 为名称,参数 2 为extend()
;3.
data
必须写成函数,避免组件被复用时,数据存在引用关系。
三、组件的嵌套
组件和组件之间可以嵌套,形成一种父子关系的组件
<div id="root">
</div>
</body>
<script>
Vue.config.productionTip = false
//定义student组件
const student = Vue.extend({
name:'student',
template:`
<div>
<h2>学生姓名:{{name}}</h2>
<h2>学生年龄:{{age}}</h2>
</div>
`,
data(){
return {
name:'张三',
age:18
}
}
})
//定义school组件
const school = Vue.extend({
name:'school',
//嵌套student组件
template:`
<div>
<h2>学生名称:{{name}}</h2>
<h2>学生地址:{{address}}</h2>
<student></student>
</div>
`,
data(){
return{
name:'张三',
address:'北京'
}
},
//注册组件(局部)
components:{
student
}
})
//定义hello组件
const hello = Vue.extend({
template:`<h1>{{msg}}</h1>`,
data(){
return{
msg:'holle vue'
}
}
})
//定义app组件
const app = Vue.extend({
//嵌套school、hello组件
template:`
<div>
<hello></hello>
<school></school>
</div>
`,
//注册组件(局部)
components:{
school,
hello
}
})
new Vue({
template:'<app></app>',
el:"#root",
//注册组件(局部)
components:{app}
})
</script>
四、组件的 props 通信
1.组件的 props
1.组件的父子关系中,当设置一个独立组件时,这个组件就是
new Vue()
的子组件;2.当我们需要通过子组件显示父组件
data
值的时候,需要通过props
属性传值
<div id="root">
<student text="李四"></student>
//也可以用 v-bind 动态绑定 props 的值到父组件的数据中。每当父组件的数据变化时,该变化也会传导给子组件:
<student v-bind:text="message"></student>
</div>
<script>
//去掉警告
Vue.config.productionTip = false;
//局部组件
const childComponent = Vue.extend({
data() {
// 子组件和父组件都有 message 属性,同时调用并不冲突;顺序也可控;
return {
message : '局部组件'
}
},
//使用传过来的text
template : `
<div>{{text}} {{message}}</div>
`,
// 声明 props
props : ['text']
});
//数据对象
const dataObj = {
message : '张三三',
};
//创建一个Vue对象
//父组件
const root = new Vue({
el : '#root',
data:dataObj,
// data(){
// return{
// message: '张三三',
// }
// },
components : {
'student' : childComponent
},
});
</script>
2.组件的 props 单向数据流
1.父组件的 data 值更新后通过 props 选项交给子组件进行渲染,反之则不行;
2.这就是单向数据流(单向下行绑定),不能通过子组件来改变父组件的状态;
3.这样做的是为了防止父组件发生改变后,数据流变得难以理解;
4.父组件更新时,子组件所有 props 值也会更新,你不能改变子组件的 props 值
<div id="root">
<html-a v-bind:count="count"></html-a>
</div>
<script>
//去掉警告
Vue.config.productionTip = false;
//局部组件
const childComponent = Vue.extend({
data() {
return {
message : '子组件',
}
},
template : `
<button v-on:click="count++">{{count}}</button>
`,
props : ['count'],
})
//创建一个Vue对象
//父组件
const root = new Vue({
el : '#root',
data : {
count : 5
},
components : {
'html-a' : childComponent
},
});
</script>
注意:
以上内容,会正确改变了 props 的值,也渲染到视图中,但控制台报错;
意为:不可以直接修改 props 值,可以通过数据或计算属性来解决;
<div id="root">
<html-a v-bind:count="count"></html-a>
</div>
<script>
//去掉警告
Vue.config.productionTip = false;
//局部组件
const childComponent = Vue.extend({
//通过使用 data 数据更改
data() {
return {
message : '子组件',
childCount : this.count
}
},
template : `
<button v-on:click="clickChildCount">{{changedChildCount}}</button>
`,
props : ['count'],
//通过使用计算属性和方法数据更改
computed: {
changedChildCount() {
return this.childCount;
}
},
methods: {
clickChildCount() {
this.childCount++
}
}
})
//创建一个Vue对象
//父组件
const root = new Vue({
el : '#root',
data : {
count : 5
},
components : {
'html-a' : childComponent
},
});
</script>
3.组件的 props 验证
1.之前
props
选项通信采用的是数组方式,其实还有第二种方式:对象;2.通过对象模式进行传递数据,可以对数据类型进行验证,支持的类似有:
Sting.Number.Boolean.Function.Object.Array.Symbo
<div id="root">
<student name="李四" sex="女" :age="18"></student>
</div>
<script>
//去掉警告
Vue.config.productionTip = false;
//局部组件
const childComponent = Vue.extend({
//通过使用 data 数据更改
data(){
console.log(this)
return{
msg:'我是一个学生',
myAge:this.age
}
},
template : `
<div>
<h1>{{msg}}</h1>
<h2>学生姓名:{{name}}</h2>
<h2>学生性别:{{sex}}</h2>
<h2>学生年龄:{{myAge+1}}</h2>
<button @click="updateAge">尝试修改收到的年龄</button>
</div>
`,
methods: {
updateAge(){
this.myAge++
}
},
//简单声明介绍
// props:['name','age','sex']
//接收的同时对数据进行类型限制
// props:{
// name:String,
// age:Number,
// sex:String
// }
//接收的同时对数据进行类型限制
props:{
name:{
type:String,//name的类型是字符串
required:true,//name是必须要的
},
age:{
type:Number,
default:18//默认值
},
sex:{
type:String,
required:true
}
}
})
//父组件
const root = new Vue({
el : '#root',
data : {
count : 5
},
components : {
'student' : childComponent
},
});
</script>
五、组件的自定义事件
父组件是使用 props 传递数据给子组件,但如果子组件要把数据传递回去,就需要使用自定义事件!
我们可以使用 v-on 绑定自定义事件, 每个 Vue 实例都实现了事件接口(Events interface),即:
- 使用
$on(eventName)
监听事件- 使用
$emit(eventName)
触发事件另外,父组件可以在使用子组件的地方直接用 v-on 来监听子组件触发的事件。
<div id="root">
{{message}}
<!-- 通过父组件给子组件绑定一个自定义事件实现:子给父传递数据(第一种写法,使用@或v-on)-->
<html-a v-on:child="parentFn"></html-a>
</div>
<script src="../js/vue.js"></script>
<script>
//去掉警告
Vue.config.productionTip = false;
//子组件
const childComponent = Vue.extend({
data() {
return {
name : 'Mr.Lon'
}
},
template : `
<div>
<button v-on:click="childClick">点我把名字传给父组件</button>
</div>
`,
methods : {
childClick() {
//触发子组件实例身上的child事件
this.$emit('child', this.name)
}
}
})
//父组件
const root = new Vue({
el : '#root',
data : {
message : 'Hello, Vue!'
},
components : {
'html-a' : childComponent
},
//方法
methods : {
parentFn(name) {
this.message = name;
console.log('子组件传递给父组件!' + name);
}
}
});
</script>