4

组件

什么是组件?

组件 (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 等实例属性还无法使用。


Allen
40 声望6 粉丝

新手上路,擅长急刹