优势一:模板化
插槽
使模板更加灵活。本质是DOM,把模板通过这个DOM放下去,通过父级的逻辑去改变子级的模板结构,使父子更加灵活。(slot带领参数以及层次结构一起传递)。
默认插槽
组件外部维护参数以及结构,内部安排放置位置。
父:
<p>{{ msg }}</p>
子:
<slot></slot>
所有没有标名字的插槽都会渲染出来,并渲染在一起。
具名插槽
以name标识插槽的身份,从而在组件内部可以做到区分开来,可放置在不同位置。
父:
<template v-slot:header>{{ header }}</template>
子:
<slot name='header' />
作用域插槽
父要子传递过来的参数,即可接收props。结构由父亲决定,内部参数由子决定。
父:
(老版本)
<template slot="content" slot-scope="{ slotProps }">{{ slotProps }}</template>
(新版本:如下不定义name时以变量名作为name)
<template v-slot:slotProps="slotProps"></template>
子:
<slot name="content" :slotProps="slotProps"/>
可利用这种形式实现react中的HOC(高阶组件):父级给HOC逻辑结构,子级往里传递参数。
模板数据的二次加工
过滤器
管道思想。与method相比:与组件状态无关,可以进行更好的解耦。
{{ timer | format }}
面试题:filter过滤器的this是否指向当前实例?
this挂载在全局vue上,this指向全局并非当前实例。filter只是个处理函数,管道符是一个纯函数,不应包含当前实例的任何状态,只对当前传入参数做处理然后返回。
v-html
指令化二次加工。不安全,可以被劫持后对页面内容做改变。
<h1 v-html="money > 99 ? 99 : money"></h1>
JSX
JSX:用JS的方式写模板。
template模板和render函数不共存。
render(h)函数:返回值为一个node节点;无需slot,变量即可是节点。
可能会涉及面试题:用JSX去实现v-model。
JSX举例:
export default {
name: 'hello',
data() {
return {
options: [{
value: 1,
text: 1,
}, {
value: 2,
text: 2,
}, {
value: 3,
text: 3,
}],
money: 100
}
},
props: {
obj: {
type: Object,
default: function() {
return {}
}
}
},
methods: {
handleClick() {}
},
render(h) {
//手写节点
const moneyNode = (
<p>{ this.money > 99 ? 99 : this.money }</p>
);
return (
<ul>
{
//jsx实现数组遍历
this.options.map((item, index) => {
return (
<li>{item.text}</li>
//组件引入实现节点嵌套
<content item={item} value={item.value} key={item.value} onClick={this.handleClick}>{moneyNode}</content>
)
})
}
</ul>
)
}
}
组件
组件化思想使得模板化更分明。
优势二:组件化
传统模板化组件
//注册
Vue.component('component', {
template: '<h1>hhhh</h1>'
});
//创建实例
new Vue({
el: '#app'
})
混入mixins
- 解释:是多个可以独立抽离的功能的复用,故返回数组。mixin不是额外的组件,它相当于是配置的延伸,把功能抽象的配置独立出来。
- 作用:主要是用来实现一些功能的复用,其中的属性和组件是一样的,例如有 data,method 等等。
- 应用:抽离公共逻辑(逻辑相同,但是模板不一样)。注重功能逻辑的复用。
- 举例:假设多个页面都会调用同一个接口来获取数据。就可以把请求方法、数据 data 都写在一个 mixin 里面。再将它混入到需要用到的页面组件中,这样就实现了功能的复用。
- 缺点:数据来源不够明确。
export default {
data() {
return {
msg: '我是mixin',
obj: {
title: 'mixinTitle',
header: 'mixinHeader'
},
aaa: 0
}
},
created() {
console.log('mixin created');
}
}
//使用
mixins: [demoMixin1, demoMixin2]
面试题:组件主体与mixins合并策略
- data冲突时:以组件主体为优先。
- 生命周期钩子:会先后执行,先mixins后主体。
- 递归合并:递归合并优先级仍以主体优先。
继承拓展extends
- 解释:提供了独立逻辑拓展能力。不是用于多重拆分和复用功能点,而是相当于复用单个组件。
- extends 是一个构造器的概念,可以基于某一个组件创建一个子类。
- 应用举例:比较典型的应用就是 ElementUI 里面的 this.$message 弹框提示的用法。内部就是通过 extends 来实现的。它首先有一个对应的弹框组件 main.vue ,通过
const x= constructor = Vue.extends(Main)
生成了这个组件的构造器。之后想要使用的时候就可以通过new constructor({ data: options })
来初始化这个实例,其中的 options就是我们可以自定义的内容,比如需要显示的文本等等。 - 应用场景:拓展独立逻辑。extends 偏向于去生成一个组件实例并对其进行扩展,传入想要传入的选项。
export default {
data() {
return {
msg: '我是extends',
obj: {
title: 'extendsTitle',
header: 'extendsHeader'
}
}
},
created() {
console.log('extends created');
}
}
//使用
extends: demoExtends
面试题:extends合并策略
与组件主体的合并策略:和mixins与组件主体的合并策略一致。
与mixins的合并策略:
- 合并优先级:mixins > extends
- 回调生命周期优先级:extends > mixins
整体拓展extend
从预定义的配置中拓展一个独立配置项,并且进行合并。
插件Vue.use(plugin)
mixins,extends,extend均是对逻辑上的扩充,不涉及模板化。而plugin对vue本身功能的补充。
使用场景:
- 注册外部插件,作为整体实例能力的补充。
- 自动做除重,防止多次重复注册相同插件。
- 编写插件:
- 外部使用时用
Vue.use(myPlugin, options)
。 - 内部默认调用install。
- 外部使用时用
export default {
install: (Vue, options) => {
Vue.globalMethod = function() {
};
Vue.directive('my-directive', {
bind(el, binding, vnode) {},
inserted(el, binding, vnode) {},
update(el, binding, vnode, oldVnode) {},
componentUpdated(el, binding, vnode) {},
unbind(el, binding, vnode) {},
});
Vue.mixin({
created() {
console.log('plugin mixin created');
}
});
Vue.prototype.$ajax = function (options) {};
}
}