vue 组件
Vue.component('my-button', { template: '<button @click="count ++">you clicked {{count}} times</button>', data: function () { // data一定要是函数的形式,否则自定义组件在复用时会影响到它的所有实例(默认:自定义组件在复用时每个实例是独立的) return { count: 0 } } })
组件是可复用的 Vue 实例,所以它们与 new Vue 接收相同的选项,例如 data、props、computed、watch、methods 以及生命周期钩子等。仅有的例外是像 el 这样根实例特有的选项。
如果想要全局使用该自定义组件,就要进行全局注册。(自定义组件命名:字母全小写且必须包含一个连字符)
<div id="components-demo">
<my-button></my-button>
</div>
new Vue({ el: '#components-demo' })
局部使用
import ComponentA from './ComponentA.vue' export default { components: { ComponentA }, // ... }
props: 父组件向子组件传递数据
StringNumberBooleanArrayObjectDateFunctionSymbol
type 除了可以是以上类型,还可以是一个自定义的构造函数,并且通过 instanceof 来进行检查确认。
function Person (firstName, lastName) { this.firstName = firstName this.lastName = lastName } Vue.component('blog-post', { props: { author: Person } })
props: { // 基础的类型检查 (`null` 和 `undefined` 会通过任何类型验证) propA: Number, // 多个可能的类型 propB: [String, Number], // 必填的字符串 propC: { type: String, required: true }, // 带有默认值的数字 propD: { type: Number, default: 100 }, // 带有默认值的对象 propE: { type: Object, // 对象或数组默认值必须从一个工厂函数获取 default: function () { return { message: 'hello' } } }, // 自定义验证函数 propF: { validator: function (value) { // 这个值必须匹配下列字符串中的一个(当 prop 验证失败的时候,(开发环境构建版本的) Vue 将会产生一个控制台的警告) return ['success', 'warning', 'danger'].indexOf(value) !== -1 } } }
向子组件传入非props属性:
首先,组件可以接受任意的特性,而这些特性会被添加到这个组件的根元素上。
<bootstrap-date-input> 组件的模板是这样的:
<input type="date" class="form-control">
为了定制一个主题(颜色):
<bootstrap-date-input data-date-picker="activated" class="date-picker-theme-dark" ></bootstrap-date-input>
对于绝大多数特性来说,从外部提供给组件的值会替换掉组件内部设置好的值。所以如果传入 type="text" 就会替换掉 type="date" 。庆幸的是,class 和 style 特性会稍微智能一些,即两边的值会被合并起来,从而得到最终的值为:form-control date-picker-theme-dark。
如果你不希望组件的根元素继承特性,你可以在组件的选项中设置 inheritAttrs: false(选项不会影响 。style 和 class 的绑定)
Vue.component('base-input', { inheritAttrs: false, props: ['label', 'value'], template: ` <label> {{ label }} <input v-bind="$attrs" v-bind:value="value" v-on:input="$emit('input', $event.target.value)" > </label> ` })
自定义组件事件绑定(通过调用内建的 $emit 方法,传入事件名称来触发一个事件,通过$emit的第二个参数来抛出一个特定的值)
Vue.component('my-button', {
template: <button @click="$emit('text-larger', 0.12)">字体放大</button>
)
在父组件中,监听这个事件的时候,我们可以通过 $event 访问到被抛出的这个值。
<my-button
......
v-on:text-larger="postFontSize += $event"
></my-button>
或者事件处理函数是一个方法
<my-button
......
v-on:text-larger="onEnlargeText"
></my-button>
methods: { onEnlargeText: function (enlargeAmount) { this.postFontSize += enlargeAmount } }
自定义输入框
Vue.component('custom-input', { props: ['value'], template: ` <input v-bind:value="value" v-on:input="$emit('input', $event.target.value)" > ` })
自定义单选框、复选框的v-model
Vue.component('base-checkbox', { model: { prop: 'checked', event: 'change' }, props: { checked: Boolean }, template: ` <input type="checkbox" v-bind:checked="checked" v-on:change="$emit('change', $event.target.checked)" > ` })
使用这个组件:
<base-checkbox v-model="lovingVue"></base-checkbox>
将原生事件绑定到组件上(使用 v-on 的 .native 修饰符)
Vue.component('base-input', { inheritAttrs: false, props: ['label', 'value'], computed: { inputListeners: function () { var vm = this // `Object.assign` 将所有的对象合并为一个新对象 return Object.assign({}, // 我们从父级添加所有的监听器 this.$listeners, // 然后我们添加自定义监听器, // 或覆写一些监听器的行为 { // 这里确保组件配合 `v-model` 的工作 input: function (event) { vm.$emit('input', event.target.value) } } ) } }, template: ` <label> {{ label }} <input v-bind="$attrs" v-bind:value="value" v-on="inputListeners" > </label> ` })
<base-input v-on:focus.native="onFocus"></base-input>
插槽(在vue 2.6中,为具名插槽和作用域插槽引入了一个新的统一的语法——v-slot,取代了以往的slot及slot-scope)
具名插槽(一个不带 name 的 <slot> 出口会带有隐含的名字“default”)
<div class="container"> <header> <slot name="header"></slot> </header> <main> <slot></slot> </main> <footer> <slot name="footer"></slot> </footer> </div>
在向具名插槽提供内容的时候,我们可以在一个 <template> 元素上使用 v-slot 指令,并以 v-slot 的参数的形式提供其名称.
<base-layout> <template v-slot:header> <h1>Here might be a page title</h1> </template> <p>A paragraph for the main content.</p> <p>And another one.</p> <template v-slot:footer> <p>Here's some contact info</p> </template> </base-layout>
现在 <template> 元素中的所有内容都将会被传入相应的插槽。任何没有被包裹在带有 v-slot 的 <template> 中的内容都会被视为默认插槽的内容。
作用域插槽
定义<current-user> 组件(user.lastName作为后备内容)
<span> <slot :user="user">{{ user.lastName }}</slot> </span>
export default { data () { return { user: { firstName: 'hi', lastName: 'Black' } } } }
在父组件中,如果<current-user></current-user>标签内写了内容,就会代替后备内容。
<current-user> <template v-slot:default="slotProps"> {{ slotProps.user.firstName }} </template> </current-user>
注意:这里在自定义组件(子组件)中需要绑定user,以便在父组件中可以拿到子组件中user的值。同时在父组件中调用时需要使用v-slot进行绑定。
如果子组件只有默认插槽,可将组件的标签当作插槽模板来使用。
<current-user v-slot:default="slotProps"> {{ slotProps.user.firstName }} </current-user>
或者更简单:
<current-user v-slot="slotProps"> {{ slotProps.user.firstName }} </current-user>
如果存在多个插槽,必要要使用完整的基于 <template> 的语法。
<current-user> <template v-slot:default="slotProps"> {{ slotProps.user.firstName }} </template> <template v-slot:other="otherSlotProps"> ... </template> </current-user>
v-slot也有缩写,即把参数之前的所有内容 (v-slot:) 替换为字符 #。例如 v-slot:header 可以被重写为 #header。但该缩写只用在具名插槽中。
<-- 正确 --> <current-user #default="{ user }"> {{ user.firstName }} </current-user> <-- 错误 --> <current-user #="{ user }"> {{ user.firstName }} </current-user>
动态组件
有的时候,需要在不同组件之间进行动态切换。通过以下方式实现:
<component v-bind:is="currentTabComponent"></component>
动态组件在每次切换时,都是重建实例,如果想要在第一次被创建的时候就缓存下来,可以使用<keep-alive> 元素。
<keep-alive> <component v-bind:is="currentTabComponent"></component> </keep-alive>

浙公网安备 33010602011771号