混入
混入 (mixin) 提供了一种非常灵活的方式,来分发 Vue 组件中的可复用功能。当组件使用混入对象时,所有混入对象的选项将被混入进该组件本身的选项。
基本应用
- 假设要混入一个方法
const userMixin={ methods:{ getInfo(){ //Fetch API 提供了一个获取资源的接口(包括跨域请求) return fetch(`/api/user/${userId}`) .then((res)=>res.json()) } } } - 使用
import userMixin from './mixins/user' Vue.component('user-com',{ mixins:[userMixin],//混入 //... mounted(){ //这个时候已经可以使用混合进来的方法了 this.getInfo(this.userId) .then((res)=>{...}) } })
同名选项
当组件和混入对象含有同名选项时,这些选项将以恰当的方式进行“合并”
- 数据对象同名,合并数据
var mixin = {
data: function () {
return {
message: 'hello',
foo: 'abc'
}
}
}
new Vue({
mixins: [mixin],
data: function () {
return {
message: 'goodbye',
bar: 'def'
}
},
})
//这时候的data:
//{ message: "goodbye", foo: "abc", bar: "def" }
- 钩子函数同名,合并方法
var mixin = {
created: function () {
console.log('混入对象的钩子被调用')
}
}
new Vue({
mixins: [mixin],
created: function () {
console.log('组件钩子被调用')
}
})
//这时候调用时:
// => "混入对象的钩子被调用"
// => "组件钩子被调用"
值为对象的选项,例如 methods、components 和 directives,将被合并为同一个对象。
全局混入
Vue.mixin({...})
自定义指令
1. 注册
- 全局注册
Vue.directive('focus', { inserted: function (el) { el.focus() } }) - 局部注册
directives: { focus: { // 指令的定义 inserted: function (el) { el.focus() } } }
使用:<input v-focus>
2. 钩子函数
bind:只调用一次,指令第一次绑定到元素时调用。inserted:被绑定元素插入父节点时调用update:所在组件的 VNode 更新时调用,但是可能发生在其子 VNode 更新之前。指令的值可能发生了改变,也可能没有。但是你可以通过比较更新前后的值来忽略不必要的模板更新 (详细的钩子函数参数见下)。componentUpdated:指令所在组件的 VNode 及其子 VNode 全部更新后调用。unbind:只调用一次,指令与元素解绑时调用。
3. 钩子函数参数
el:指令所绑定的元素,可以用来直接操作 DOM。binding:一个对象,包含以下 property:name:指令名,不包括 v- 前缀。value:指令的绑定值,例如:v-my="1 + 1" 中,绑定值为 2oldValue:指令绑定的前一个值,仅在 update 和 componentUpdated 钩子中可用expression:字符串形式的指令表达式。例如 v-my="1 + 1" 中,表达式为 "1 + 1"。arg:传给指令的参数。例如 v-my:foo 中,参数为 "foo"modifiers:一个包含修饰符的对象。例如:v-my.foo.bar 中,修饰符对象为 { foo: true, bar: true }。
vnode:Vue 编译生成的虚拟节点。oldVnode:上一个虚拟节点,仅在 update 和 componentUpdated 钩子中可用
插件
插件通常用来为 Vue 添加全局功能。插件的功能范围没有严格的限制——一般有下面几种:
- 添加全局方法或者 property。如:vue-custom-element
- 添加全局资源:指令/过滤器/过渡等。如 vue-touch
- 通过全局混入来添加一些组件选项。如 vue-router
- 添加 Vue 实例方法,通过把它们添加到 Vue.prototype 上实现。
- 一个库,提供自己的 API,同时提供上面提到的一个或多个功能。如 vue-router
//全局使用
Vue.use(MyPlugin)
//传入选项
Vue.use(MyPlugin, { someOption: true })
// 用 Browserify 或 webpack 提供的 CommonJS 模块环境时
var Vue = require('vue')
var VueRouter = require('vue-router')
// 不要忘了调用此方法
Vue.use(VueRouter)
过滤器
1. 注册
- 全局注册
//将字母转为大写 Vue.filter('capitalize', function (value) { if (!value) return '' value = value.toString() return value.charAt(0).toUpperCase() + value.slice(1) }) - 局部注册
//在组件选项中: filters: { capitalize: function (value) { //... } }
2. 使用
过滤器可以用在两个地方:
- 双花括号插值
{{ message | capitalize }} v-bind表达式<div :id="rawId | formatId"></div>
3. 链式调用
在下面的例子中,首先会调用round过滤器,它返回的结果会传递给formatCost过滤器进行处理:
{{ productOneCost | round |formatCost}}
4. 参数
{{ message | filterA('arg1', arg2) }}
其中 message 的值作为第一个参数,普通字符串 'arg1' 作为第二个参数,表达式 arg2 的值作为第三个参数。
单文件组件
全局组件的缺点:
- 全局定义强制要求每个 component 中的命名不得重复
- 字符串模板缺乏语法高亮,看不清晰
- 不支持 CSS ,意味着当 HTML 和 JavaScript 组件化时,CSS 明显被遗漏
- 没有构建步骤,限制只能使用 HTML 和 ES5 JavaScript,而不能使用预处理器,如 Pug 和 Babel
文件扩展名为 .vue 的 单文件组件为以上所有问题提供了解决方法,并且还可以使用 webpack 或 Browserify 等构建工具
以下是一个文件名为Hello.vue的简单实例
<template>
<p>Hello!{{msg}}</p>
</template>
<script>
export default{
name:'test',
props:{
msg:{
type:String,
default:"test msg"
}
},
methods:{}
data () {
return {
name: 'lihua'
}
}
}
</script>
<style scoped>
p{color: antiquewhite;}
</style>
在其他地方中使用
<template>
<div id="app">
<test></test>
</div>
</template>
<script>
//1. 引入组件
import test form './components/test.vue'
export default{
name:'app',
//2. 注册组件
components:{
test
}
}
</script>