Vue 组件注册
-
全局注册
Vue.componet('my-component-name', { // 选项 })
全局注册的组件在注册之后,可以用在其被注册之后的任何 (通过
new Vue
) 新创建的 Vue 根实例,也包括其组件树中的所有子组件的模板中。 -
局部注册
var ComponentA = { 选项 } new Vue({ el: '#app', components: { 'component-a': ComponentA } })
局部注册的组件只在注册组件中可用,在其子组件中不可用。
注意:不管哪种注册方式, data 选项都必须是函数
Vue.extend(options)
使用基础的 Vue 构造器,创建一个子类,参数是一个包含组件选项的对象。 data 选项是特例,需要注意 - 在 Vue.extend 中它必须是函数。
<div id="mount-point"></div>
// 创建构造器
var Profile = Vue.extend({
template: '<p>{{firstName}} {{lastName}} aka {{alias}}</p>',
data: function () {
return {
firstName: 'Walter',
lastName: 'White',
alias: 'Heisenberg'
}
}
})
// 创建 Profile 实例,并挂载到一个元素上。
new Profile().$mount('#mount-point')
结果如下:
<p>Walter White aka Heisenberg</p>
vue-loader
我们在开发使用 vue-cli 搭建的 web 应用时写的最多的就是单文件组件(.vue),在 webpack 配置文件中我们会使用 vue-loader 处理 .vue 文件,配置如下:
// webpack.config.js
module: {
rules: [
{
test: /\.vue$/,
loader: 'vue-loader',
options: vueLoaderConfig
},
...
]
}
.vue 文件可以包含三种类型的顶级语言块 <template>
、<script>
和 <style>
,还允许添加可选的自定义块:
-
模板块 template
一个 .vue 中最多一个
<template>
块,其内容将被提取为字符串传递给 vue-template-compiler ,最终它被编译为 js 渲染函数,并注入到从<script>
导出的组件中。 -
脚本块 script 一个 .vue 最多一个
<script>
块,会被编译成一个模块封装函数。它的默认导出应该是一个 Vue.js 的组件选项对象,也可以导出由Vue.extend()
创建的扩展对象。 -
样式块 style
一个 .vue 文件可以包含多个
<style>
标签,标签可以有scoped
或者module
属性。 -
自定义语言块
vue-loader 将会使用块名来查找对应的 loader 进行处理。
下面是一个典型的单组件文件 hello.vue
<template>
<div class="address">{{ addr }}</div>
</template>
<style>
export default {
name: 'component-a',
data () {
return {
addr: 'shenzhen'
}
}
}
</style>
<style scoped>
.address {
color: 'red'
}
</style>
假如我们在 App.vue 中引入这个组件,如下:
<template>
<div id="app">
<img src="./assets/logo.png" />
<button @click="handleClick">Button</button>
</div>
</template>
<script>
import Hello from './views/hello.vue'
import Vue from 'vue'
export default {
name: "App",
methods: {
handleClick () {
this.$toast('I am clicked');
}
},
components: {
hello: Hello
},
created() {
console.log(Hello);
const HelloComp = Vue.extend(Hello);
const HelloComp1 = new HelloComp();
const HelloComp2 = new HelloComp();
console.log(HelloComp1.addr) // 'shenzhen'
console.log(HelloComp2.addr) // 'shenzhen'
HelloComp1.addr = 'shanghai'
console.log(HelloComp1.addr) // 'shanghai'
console.log(HelloComp2.addr) // 'shenzhen'
}
};
</script>
我们在 created 中打印 Hello 来看看它是什么,可以看出就是一个普通的对象,并且 <template>
已经被编译成 render 函数注入到这个对象中。
当在 components 选项中注册 hello 时,vue 会调用 Vue.extend(hello),在其中还会检查 hello.data 是不是 function 类型,然后返回 Sub = function VueComponent(options) 函数(如下),并且 Sub.options 包含 hello(除此还添加了一些其他选项),最终生成一个 VNode 对象。
function VueComponent (options) {
this._init(options)
}
当在 template 中使用 <hello />
时,其实是使用 Sub 函数创建一个实例。
写一个通用组件
ModalVerifyPassword.vue
<template>
<el-dialog title="登陆验证" :visible.sync="isVisible">
<el-form :model="form">
<el-form-item label="密码" prop="pass">
<el-input type="password" v-model="form.pass" autocomplete="off"></el-input>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="onCancel">取 消</el-button>
<el-button type="primary" @click="onVerify">确 定</el-button>
</div>
</el-dialog>
</template>
<script>
export default {
name: 'modal-verify-password',
data() {
return {
isVisible: false,
form: {
pass: '',
},
formLabelWidth: '120px'
};
},
methods: {
onCancel() {
this.isVisible = false
},
onVerify() {
this.isVisible = false
}
}
};
</script>
modal-verify-password.js
import Vue from 'vue';
import store from '@/store';
import ModalVerifyPassword from '@/components/modal-verify-password';
let instance = null;
const open = () => {
if (!instance) {
instance = new Vue({
...ModalVerifyPassword,
});
const component = instance.$mount();
document.body.appendChild(component.$el);
}
instance.isVisible = true;
};
export default {
open
};
最后全局注册,就能在所有组件中调用。