组件常用属性:
1.1、directive
1.2、computed
1.3、watch
1.4、filter
1.5、mixin
2.1、directive
directive,该属性用于自定义指令。
自定义指令可以分为两种情况:
-
全局自定义指令【更加实用】
-
局部自定义指令
当在某个组件内,自身的局部自定义指令与全局自定义指令冲突时,以组件自身的局部自定义指令为准。
指令是帮助我们快速完成某些处理的语法糖,其本质也就是一些拥有固定函数名称的函数集合,这些函数会在特定的时间触发并自动执行,我们称之为钩子函数。指令支持以下钩子函数
bind,当指令首次与标签元素绑定的时候触发
inserted,当标签元素被插入完成后触发(与bind的区别在于是否可以获取父节点)
update,当标签元素更新时触发
componentUpdated,当组件更新完毕后触发
unbind,当指令与标签解绑时触发
在自定义指令时,我们必须要根据业务需要从上面几个钩子函数中选取一个或几个合适的钩子函数,并准备好逻辑代码组成一个JavaScript对象。钩子函数支持俩个形参:
-
el:指令宿主对应的DOM对象
-
binding:指令绑定对象,可以通过该对象获取指令的名称、指令表达式等信息
全局自定义指令的注册,通常也是在入口文件main.js中完成,但指令的处理程序在编写的时候允许模块化,也建议采用模块化来保持入口文件中的代码可读性。
Vue.directive("不带v-的指令名",包含指令处理程序的对象)
局部自定义指令通常注册在对应的组件自身,处理程序自身往往也不需要模块化,可以直接写在组件内,当然如果这个指令也需要在其它组件中使用也是可以模块化的:
export default {
directives: {
// 不带v-的指令名: 包含指令处理程序的对象,
}
}
※ 在自定义指令的方法中,不能像以前的methods
中的方法一样使用关键词this
,此时this
关键词指向undefined
。
案例:使用自定义指令实现以下效果
-
使用全局指令定义自定义的
v-color(传参)
,在元素被插入时设置内容颜色
例如:<div v-color="'red'">文字</div>
此时指令语法如下:
// 指令实则是一堆钩子函数的集合
// 使用全局指令定义自定义的`v-color(传参)`,在元素被插入时设置内容颜色
const obj = {
bind (el) {
// 获取不到父节点
console.log(el.parentNode)
},
inserted (el, binding) {
console.log(el, binding)
// 获取父节点
console.log(el.parentNode)
el.style.color = binding.value
}
}
export default obj
需要在入口文件main.js中导入并注册指令:
import color from './directives/color'
// 全局指令注册语法:Vue.directive(指令名,指令对象)
Vue.directive('color', color)
在App.vue文件中测试全局指令的使用:
<template>
<div>
<!-- 全局指令测试 -->
<div v-color="color">青山哥哥好帅啊</div>
<div v-color="'green'">青山哥哥好帅啊</div>
<div v-color="'blue'">青山哥哥好帅啊</div>
<div v-color="'pink'">青山哥哥好帅啊</div>
<div v-color="'orange'">青山哥哥好帅啊</div>
<div v-color="'grey'">青山哥哥好帅啊</div>
</div>
</template>
<script>
export default {
data () {
return {
color: 'red'
}
},
}
</script>
<style></style>
2.2、computed
computed,该属性用于定义计算属性
计算属性没有全局和局部之分,按照以下语法声明计算属性:
export default {
computed: {
// 计算属性名 : Function,
}
}
计算属性默认只有 getter,不过在需要时你也可以提供一个setter:
export default {
computed: {
// 计算属性名 : { get: Function, set: Function },
}
}
-
get:对应的函数在调用该计算属性时被执行
-
set:对应的函数在给该计算属性赋值时被执行,形参为赋的值
计算属性的结果会被缓存,除非依赖的响应式数据变化才会重新计算。注意,如果某个依赖 (比如非响应式 property) 在该实例范畴之外,则计算属性是不会被更新的。
2.3、watch
watch,该属性用于定义监听器/侦听器
使用watch来侦听data中数据的变化,watch中的属性(watch是对象格式)一定是data 中已经存在的数据。(特殊情况除外)
使用场景:数据变化时执行异步或开销比较大的操作。
典型应用:在线汉字转拼音
监听器的语法如下:
export default {
watch: {
data中数据属性名: 函数名 | 函数 | 对象 | 回调函数数组,
}
}
特别需要注意,如果监听的数据是一个对象,则需要使用深度监听语法:
export default {
watch: {
data中对象属性名: {
deep: true,
handler(val,oldVal){
}
}
}
}
== 面试题:computed与watch有什么区别?? ==
设计方式上的区别
计算属性:依赖数据的,只要数据不变,它会套用固定的流程去执行。我们写好之后一劳永逸的。
监听器:需要我们自己去写比较复杂的数据处理过程,比如说一些异步的操作、开销大的操作。
响应方式上的区别
计算属性:支持深度数据是否变化的监听的
监听器:默认不支持深度响应,仅支持字面量处理,但是其支持通过代码的改动来支持深度监听
2.4、filter
filter,该属性用于定义过滤器
注意:filter仅在Vue2.x中支持,Vue3.x中已废弃,针对后者建议通过computed或methods来替代实现
过滤器没有全局和局部之分,哪个组件需要使用则在对应的组件中声明即可,例如:
export default {
filters: {
过滤器名: Function,
}
}
需要注意的是,过滤器对应的函数:
至少有1个形参,形参为待处理的数据(任意格式)
使用过滤器时,如果实参有n个,那么形参应该有n+1个;其中第一形参必定是待处理的数据,而后的形参与实参一一对应(例如:第二个形参对应着第一个实参,第三个形参对应着第二个实参....)
必须有返回值。
2.5、mixin
mixin,该属性用于定义混入
mixin是Vue中非常实用的一个功能,它能够实现一些代码片段的复用,它可以将一个混入对象(js普通对象)中的Vue选项混入到被混入的Vue组件中去。混入操作按照类型可以分为:
-
全局混入,全局混入也可以称之为叫强制混入
-
局部混入,局部混入也可以称之为叫按需混入
全局混入会将混入对象的选项混入到所有的Vue组件中去,除非项目中每个组件都需要这些Vue选项,否则该操作方式慎用,因为其可能导致其它组件运行不正常。
定义混入对象,混入对象与常规的Vue选项对象的声明基本一致,假设混入对象名称为obj,则:
// 将要复用的选项放到混入对象中去
const obj = {
methods: {}
data(){
return {}
},
filters: {
},
computed: {
},
// ....
}
它不一定需要所有的Vue选项,需要什么根据复用的需求而定,需要复用什么选项写入进去即可。但是由于工程化下整个项目共用一个Vue的el
选项,因此混入对象中一般不会有el
选项。
全局混入语法:
Vue.mixin(混入对象)
局部混入语法:
export default {
mixins: [混入对象1,混入对象2,....]
}
在一个混入对象被混入到一个组件的时候,混入对象中的选项可能与组件自身的选项存在冲突的情况,例如混入对象中的data中有一个msg属性,而组件自身的data中也有msg属性,在这种情况下,混入操作会按照固定的合并策略进行冲突合并:
如果冲突发生在data中,则以组件自身的data数据为准
如果是对象属性发生冲突(如methods、computed、filters等)则会合并成一个对象属性,如对象属性中的属性存在同名则以组件自身的为准
如果是钩子函数出现同名冲突,则混入对象中的钩子函数会与本组件自身的钩子函数合并成数组,所有钩子函数均会被执行,但同周期的钩子函数在执行的时候混入对象中的钩子函数会优先于本组件的钩子函数执行。
1.钩子函数
同名钩子函数将会混合为一个数组,都将被调用到,但是混入对象的钩子将在组件自身钩子之前调用。
var mixin = {
created: function () {
console.log('混入对象的钩子被调用')
}
}
new Vue({
mixins: [mixin],
created: function () {
console.log('组件钩子被调用')
}
})
// => "混入对象的钩子被调用"
// => "组件钩子被调用"
2.数据对象合并
<body>
<div id="app"></div>
</body>
<script src="./vue.js"></script>
<script>
var Mixins = {
data: {
msg: 'I am Mixins',
msg1: 'I am Mixins msg1'
},
created() {
console.log('我是组件中的变量:' + this.msg2)
}
}
new Vue({
mixins: [Mixins],
el: '#app',
data: {
msg: 'I am #app',
msg2: 'I am msg2'
},
created() {
console.log(this.msg)
console.log('我是混入对象中的变量:' + this.msg1)
}
})
// 我是组件中的变量:I am msg2
// I am #app
// 我是混入对象中的变量:I am Mixins msg1
</script>
3.普通方法合并
当混合值为对象的选项时,例如 methods、components、directive,将被混合为同一个对象,两个对象键名冲突时,取组件对象的键值对。
<body>
<div id="app"></div>
</body>
<script src="./vue.js"></script>
<script>
var Mixins = {
methods: {
mixin: function() {
console.log('Mixin')
},
mixinTwo: function () {
console.log('MixinTwo')
}
}
}
new Vue({
el: '#app',
mixins: [Mixins],
methods: {
mixin: function () {
console.log('#app')
}
},
mounted() {
this.mixin()
this.mixinTwo()
}
})
// #app
// MixinTwo
</script>
4.局部混入
在componnets目录下新建mixins文件夹,并在mixins目录下创建一个mixin.js文件,代码如下:
const mixin = {
data() {
return {
msg: "hello"
}
},
methods: {
mixinMethod() {
console.log(this.msg + ',这是mixin混入方法')
}
}
}
export default mixin;
在需要的页面中引入:
<template>
<div>{{msg}}</div>
</template>
<script>
import mixin from '../mixins/mixin'
export default {
mixins: [mixin],
data() {
return {
}
}
mounted() {
this.mixinMethod()
}
}
// hello,这是mixin混入的方法
5.全局混入
在main.js加入以下代码
Vue.mixin({
data() {
return {
msg: 'hello'
}
},
methods: {
mixinMethod() {
console.log(this.msg+',这是mixin混入的方法')
}
}
})
在组件中直接引用:
<template>
<div>{{msg}}</div>
</template>
<script>
export default {
data() {
return {
}
}
mounted() {
this.mixinMethod()
}
}
// hello,这是mixin混入的方法
</script>
2.6、mixin与vuex的区别
mixin混入对象和Vuex的区别:
1、Vuex是状态共享管理,所以Vuex中的所有变量和方法都是可以读取和更改并相互影响的;
2、mixin可以定义公用的变量或方法,但是mixin中的数据是不共享的,也就是每个组件中的mixin实例都是不一样的,都是单独存在的个体,不存在相互影响的;
3、mixin混入对象值为函数的同名函数选项将会进行递归合并为数组,两个函数都会执行,只不过先执行mixin中的同名函数;
4、mixin混入对象值为对象的同名对象将会进行替换,都优先执行组件内的同名对象,也就是组件内的同名对象将mixin混入对象的同名对象进行覆盖;
2.7、mixin与父子组件的区别
组件在引用之后相当于在父组件内开辟了一块单独的空间,来根据父组件props过来的值进行相应的操作,但本质上两者还是泾渭分明,相对独立。
而mixins则是在引入组件之后,将组件内部的内容如data等方法、method等属性与父组件相应内容进行合并。相当于在引入后,父组件的各种属性方法都被扩充了。
单纯组件引用:父组件 + 子组件 >>> 父组件 + 子组件
mixins:父组件 + mixin组件 >>> new父组件
mixin作用:多个组件可以共享数据和方法,在使用mixin的组件中引入后,mixin中的方法和属性也就并入到该组件中,可以直接使用。钩子函数会两个都被调用,mixin中的钩子首先执行。