Vue.component('component-a',{组件的选项对象}|组件构造器);
组件构造器:作用一:用于给
Vue.component()
创建注册组件;作用二:用于new 创建组件实例;
// 注册组件,传入一个扩展过的构造器 Vue.component('my-component', Vue.extend({ /* ... */ })) // 注册组件,传入一个选项对象 (自动调用 Vue.extend) Vue.component('my-component', { /* ... */ }) 例子:const cpn = Vue.extend({ template:` <div> <p>我是父组件</p> </div> ` })//创建组件构造器 Vue.component('cpn1',cpn);//注册全局组件, -------------- 构造器的另一个用途: import Toast from './Toast' // 导入组件选项对象 const toastConstructor = Vue.extend({Toast})//生成组件构造器 const toast = new toastConstructor()/创建实例,组件对象,生命周期开始 toast.$mount(document.createElement('div'))/手动挂载(完全替换)到一个新元素上,此时新元素还不在页面上 /相当于子组件执行完了mounted钩子函数 document.body.appendChild(toast.$el)/最后将新元素添加到body元素
new Vue({...,components:{component-a:{子组件的选项对象}}})
import ComponentA from './ComponentA.vue' export default { components: { ComponentA }, // ... }
用于自动化全局注册多个公共组件;
使用基于webpack的require.context方法;
全局注册的行为必须在根 Vue 实例 (通过 new Vue) 创建之前发生。
require.context返回值类似: {
“./A.js”: Module,
“./B.js”: Module,
“./C.js”: Module,
“./D.js”: Module
};
src/main.js: import Vue from 'vue' import upperFirst from 'lodash/upperFirst' import camelCase from 'lodash/camelCase'//先转为小驼峰,再用首字母大写,转为大驼峰 const requireComponent = require.context( './components', // 其组件目录的相对路径 false, // 是否查询其子目录 /Base[A-Z]\w+\.(vue|js)$/ // 匹配基础组件文件名的正则表达式 ) requireComponent.keys().forEach(fileName => { // 获取组件配置 const componentConfig = requireComponent(fileName) // 获取组件的 PascalCase 命名 const componentName = upperFirst( camelCase( // 获取和目录深度无关的文件名 fileName .split('/') .pop() .replace(/\.\w+$/, '') ) ) // 全局注册组件 Vue.component( componentName, // 如果这个组件选项是通过 `export default` 导出的, // 那么就会优先使用 `.default`, // 否则回退到使用模块的根。 componentConfig.default || componentConfig ) })
<blog-post post-title="hello!"></blog-post> Vue.component('blog-post', { // 在 JavaScript 中是 camelCase 的 props: ['postTitle'], template: '<h3>{{ postTitle }}</h3>' })
props: ['title', 'likes', 'isPublished', 'commentIds', 'author']; props: { title: String, likes: Number, isPublished: Boolean, commentIds: Array, author: Object, callback: Function, contactsPromise: Promise // or any other constructor } 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) { // 这个值必须匹配下列字符串中的一个 return ['success', 'warning', 'danger'].indexOf(value) !== -1 } } } })
""
; 这是一个 JavaScript 表达式而不是一个字符串。<blog-post v-bind:comment-ids="[234, 266, 273]"></blog-post> <blog-post v-bind:comment-ids="post.commentIds"></blog-post>
post: { id: 1, title: 'My Journey with Vue' } <blog-post v-bind="post"></blog-post> ==> <blog-post v-bind:id="post.id" v-bind:title="post.title" ></blog-post>
对于绝大多数 attribute 来说,从外部提供给组件的值会替换掉组件内部设置好的值。庆幸的是,class 和 style attribute 会稍微智能一些,即两边的值会被合并起来,从而得到最终的值:
<bootstrap-date-input data-date-picker="activated"></bootstrap-date-input> 组件内部没有props接收这个属性的话,类似于普通属性 class="actived", data-date-picker="activated" 就会自动添加到 <bootstrap-date-input> 的根元素上。
借助inheritAttrs: false(设置不自动使用外界属性)、v-bind="$attrs"(哪个元素需要外界传的属性就添加这个)
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> ` }) ----单文件中 export default { inheritAttrs: fasle, } 使用: <base-input v-model="username" required placeholder="Enter your username" ></base-input> ----
<my-component v-on:my-event="doSomething"></my-component> this.$emit('my-event')
一个组件上的 v-model 默认会利用名为 value 的 prop 和名为 input 的事件,
但是像单选框、复选框等类型的输入控件可能会将 value attribute 用于不同的目的。
所以在子组件内部不是输入框时,添加model 选项,可以用来避免这样的冲突:
<base-checkbox v-model="lovingVue"></base-checkbox> ==相当于 <base-checkbox :checked="lovingVue" @change="var=>{lovingVue = var}"></base-checkbox> ----子组件如下: Vue.component('base-checkbox', { model: { prop: 'checked', event: 'change' },//用于指定父组件在v-model对应以哪个属性传进来,并通过哪个事件接收 props: { checked: Boolean }, template: ` <input type="checkbox" v-bind:checked="checked" v-on:change="$emit('change', $event.target.checked)" > ` })