组件
什么是组件?
组件 (Component) 是 Vue.js 最强大的功能之一。组件可以扩展 HTML 元素,封装可重用的代码。在较高层面上,组件是自定义元素,Vue.js 的编译器为它添加特殊功能。在有些情况下,组件也可以表现为用 is 特性进行了扩展的原生 HTML 元素。
也可分为:
有结构HTML
有样式CSS
有交互(效果)
行为
信号量存数据
系统组件
<input type="number" style="outline: 10px solid red" step="3" min="0" max="30" oninput="console.log(1)" onclick="change()">
组件的行为可以定制?通过属性设置
在Vue中有什么样的组件(组件进行分类):
实现基本功能的基础的组件(最小的元素)
可复用的逻辑组件(业务组件)
页面组件页面上所有的东西全都是组件:形成了组件树
局部注册–自定义组件
你不必把每个组件都注册到全局。你可以通过某个 Vue 实例/组件的实例选项 components 注册仅在其作用域中可用的组件:
<child></child>//在html中是使用
var Child = {
template: '<div>A custom component!</div>'
}
var vm = new Vue({
el: "#app",
components: {
// Child 将只在父组件模板中可用
Child
}
})
这种封装也适用于其它可注册的 Vue 功能,比如指令。
组件树
页面上所有的东西全都是组件:形成了组件树
// 头部组件
var AppHead = {
template: `<div>app head</div>`
};
// 主窗口单元组件
var AppMainUnit = {
template: `<div>app main unit</div>`
}
// 主窗口组件
var AppMain = {
template: `<div>app main
<app-main-unit></app-main-unit>
<app-main-unit></app-main-unit>
</div>`,
components: {
AppMainUnit
}
}
// 侧边栏单元组件
var AppSideUnit = {
template: `<div>app side unit</div>`
}
// 侧边栏组件
var AppSide = {
template: `<div>app side
<app-side-unit></app-side-unit>
<app-side-unit></app-side-unit>
<app-side-unit></app-side-unit>
</div>`,
comp
onents: {
AppSideUnit
}
}
// 根组件
var vm = new Vue({
el: "#app",
components: {
AppHead,
AppMain,
AppSide
}
})
组件data
子组件与根组件的data用法不同
根组件data:
var vm = new Vue({
el: "#app",
data: {
msg: ''
},
components: {
MyLi
}
})
<div>{{msg}}</div>调用其中的msg
子组件data:
var MyLi = {
//那么 Vue 会停止运行,并在控制台发出警告,告诉你在组件实例中 data 必须是一个函数。
data() {
console.log(1);
return {
counter: 0
}
},
template: `<button @click='counter++'>{{counter}}</button>`
}
//根组件
var vm = new Vue({
el: "#app",
data: {
msg: '123'
},
components: {
MyLi
}
})
<my-li></my-li>
<my-li></my-li>
<my-li></my-li>
输出结果:0 0 0
props声明
组件实例的作用域是孤立的。这意味着不能 (也不应该) 在子组件的模板内直接引用父组件的数据。父组件的数据需要通过 prop 才能下发到子组件中。
var Child = {
template: `<span >{{message}}{{myMessage}}</span>`,
//声明当前组件内部能够接受一个message的属性,如果是驼峰式命名,在传递参数时使用小写,
props: ['message','myMessage']
}
var vm = new Vue({
el: '#app',
data: {
parentMessage:'h'
},
components: {
Child
}
})
在html中使用:
<child message="hello" :my-message="parentMessage"></child>//父组件赋值到子组件
<child message="hi"></child>
<input type="text" v-model="parentMessage"/>//实时同步的pareMessage值
props–作为组件内部的初始状态
Prop 是单向绑定的:当父组件的属性变化时,将传导给子组件,但是反过来不会。这是为了防止子组件无意间修改了父组件的状态,来避免应用的数据流变得难以理解。
另外,每次父组件更新时,子组件的所有 prop 都会更新为最新值。这意味着你不应该在子组件内部改变 prop。如果你这么做了,Vue 会在控制台给出警告。
在两种情况下,我们很容易忍不住想去修改 prop 中数据:
Prop 作为初始值传入后,子组件想把它当作局部数据来用;
Prop 作为原始数据传入,由子组件处理成其它数据输出。
var Child = {
template: `<div @click="childCounter++">{{initCounter}} {{childCounter}}</div>`,
props:['initCounter'],
data(){
//保存初始值到childCounter并返回,发生变化的是当前的childCounter的值
return {childCounter: this.initCounter}
}
}
var vm = new Vue({
el: "#app",
data: {
counter: 0
},
components:{
Child
}
})
在html中调用:
<child :init-counter="counter"></child>
props的计算后属性
注意在 JavaScript 中对象和数组是引用类型,指向同一个内存空间,如果 prop 是一个对象或数组,在子组件内部改变它会影响父组件的状态。
var Child = {
template: `<div>{{size}} {{normalSize}}</div>`,
props: ['size'],
computed: {
normalSize(){
return this.size.trim().toLowerCase();
}
}
}
var vm = new Vue({
el: "#app",
data:{
parentSize: ' THREE'
},
components:{
Child
}
})
在html中调用:
<child :size="parentSize"></child>
props–验证
我们可以为组件的 prop 指定验证规则。如果传入的数据不符合要求,Vue 会发出警告。这对于开发给他人使用的组件非常有用。
要指定验证规则,需要用对象的形式来定义 prop,而不能用字符串数组:
var Child = {
template: `<div>{{pa}} {{pb}} {{pc}} {{pd}} {{pe}} {{pf}}</div>`,
props: {
pa: Number,
pb: [String, Number],
pc: {
type: Number,
required: true//必填
},
pd: {
type: Number,
default: 100//默认值
},
pe: {
type: Object,
default: function(){
return {
hello : "world"
}
}
},
pf: {
type: Number,
validator: function(v){
return v > 100
}//自定义属性判断
}
}
}
var vm = new Vue({
el: "#app",
data:{
pa: 2,
pb: "abc",
pc: 2,
pd: 50,
pe: {},
pf: 120
},
components:{
Child
}
})
在html中使用:
<child :pa="pa" :pb="pb" :pc="pc" :pd="pd" :pe="pe" :pf="pf"></child>
type 可以是下面原生构造器:
String
Number
Boolean
Function
Object
Array
Symbol
type 也可以是一个自定义构造器函数,使用 instanceof 检测。
当 prop 验证失败,Vue 会抛出警告 (如果使用的是开发版本)。注意 prop 会在组件实例创建之前进行校验,所以在 default 或 validator 函数里,诸如 data、computed 或 methods 等实例属性还无法使用。