Vue可复用解决方案
目录
一. 自定义指令
1.1.全局指令
1.2.局部指令
1.3.指令参数
二. Mixin混入
2.1.基本用法
2.2. 混入优先级
2.3.全局 Mixin
三. 插件
3.1.基本用法
3.2.给Vue扩展功能
一个项目是由很多组件组成的。而组件之间可能存在很多相似的功能,如果我们在每个组件中去重复定义这些功能,会使得项目出现代码冗余并提高了维护难度。针对这种情况官方提供了很多可复用解决方案,比如:自定义指令、Mixin、插件等。
一. 自定义指令
除了核心功能默认内置的指令 (例如 v-model 和 v-show 等),Vue 也允许创建自己的指令。自己做的指令中可以封装某个功能,这样就能达到复用代码的目的。
1.1.全局指令
下面实例中自定义一个全局指令,能够显示当前时间。
<body>
<div id="app">
<div v-date></div>
<div v-date></div>
</div>
<script src="https://unpkg.com/vue@next"></script>
<script>
let app = Vue.createApp({});
app.directive('date', {
mounted(el) {
el.innerHTML = new Date();
}
})
//注意这里:需要先声明自定义指令后再绑定视图
app.mount('#app');
</script>
</body>
使用Vue实例中的directive函数创建自定义指令。第一个参数是指令名,第二个参数是指令内容。
自定义指令中,使用了 mounted 生命周期,因为需要操作DOM。
mounted 生命周期函数中有一个参数,此参数就是使用指令的DOM对象。
使用时指令依然为 “v-指令名” 的形式。
上面自定义指令直接挂载到Vue实例上,所以是全局指令
1.2.局部指令
下面单独创建自定义指令,然后在Vue实例中引用这个指令,所以是局部指令。
<body>
<div id="app">
<div v-date></div>
<div v-date></div>
</div>
<script src="https://unpkg.com/vue@next"></script>
<script>
const mydirective = {
date: {
mounted(el) {
el.innerHTML = new Date();
}
}
}
let app = Vue.createApp({
data() {
return {
}
},
directives: mydirective
});
app.mount('#app');
</script>
</body>
- 上面代码中,单独创建一个自定义指令,所以需要在Vue实例中使用directives属性引用这个指令。
1.3.指令参数
指令作为封装好的一段功能代码,应该具有参数功能,这样才能更加灵活的封装代码。
下面实现一个带参数的自定义指令,它能够将图片按照指定大小显示成圆形图片。
<body>
<div id="app">
<img src="img/gf01.jpeg" v-imgcir="200">
</div>
<script src="https://unpkg.com/vue@next"></script>
<script>
const mydirective = {
imgcir: {
mounted(el,binding) {
el.style.width = binding.value+'px';
el.style.height = binding.value+'px';
el.style.borderRadius = (binding.value/2)+'px';
}
}
}
let app = Vue.createApp({
data() {
return {
}
},
directives: mydirective
});
app.mount('#app');
</script>
</body>
首先,在视图层使用自定义指令时添加一个参数值。
自定义指令可以使用binding来接收这个参数,并使用binding.value的形式获取。
二. Mixin混入
官方解释:Mixin 提供了一种非常灵活的方式,来分发 Vue 组件中的可复用功能。一个 mixin 对象可以包含任意组件选项。当组件使用 mixin 对象时,所有 mixin 对象的选项将被“混合”进入该组件本身的选项。
2.1.基本用法
<body>
<div id="app">
<p>num:{
{num}}</p>
<p>name:{
{name}}</p>
</div>
<script src="https://unpkg.com/vue@next"></script>
<script>
const common = {
data(){
return {
name: '张三'
}
}
}
let app = Vue.createApp({
data() {
return {
num: 10
}
},
mixins: [common]
});
app.mount('#app');
</script>
</body>
先定义共通内容。再使用mixins属性将此内容混入到Vue实例中。
此时,Vue实例中就可以使用混入的内容了。
2.2. 混入优先级
一个 mixin 中可以书写 Vue 中的任何选项,包括 data、methods、计算属性等等。那么,如果混入内容与Vue原有选项内容有冲突时如何处理呢?
<body>
<div id="app">
<p>num:{
{num}}</p>
<button @click="add">点击</button>
</div>
<script src="https://unpkg.com/vue@next"></script>
<script>
const common = {
data(){
return {
num: 20
}
},
methods:{
add(){
console.log('Mixin事件');
}
},
created(){
console.log('Mixin生命周期');
}
}
let app = Vue.createApp({
data() {
return {
num: 10
}
},
mixins: [common],
methods:{
add(){
console.log('Vue实例事件');
}
},
created(){
console.log('Vue生命周期');
}
});
app.mount('#app');
</script>
</body>
通过上面实例可以发现优先级规则:
在mixin与组件选项有重叠时,组件选项优先级高于mixin选项。
但生命周期函数会先执行mixin的生命周期函数,再执行组件的。
2.3.全局 Mixin
Mixin 也可以进行全局注册。也就是将Mixin直接挂载到Vue实例上,这样,组件中就不用再写mixins: [common]选项了。这就是全局Mixin。
<body>
<div id="app">
<p>num:{
{num}}</p>
<button @click="add">点击</button>
</div>
<script src="https://unpkg.com/vue@next"></script>
<script>
let app = Vue.createApp({
data() {
return {
num: 10
}
},
//mixins: [common],
methods:{
add(){
console.log('Vue实例事件');
}
},
created(){
console.log('Vue生命周期');
}
});
//将 Mixin直接挂载到Vue实例上
app.mixin({
data(){
return {
num: 20
}
},
methods:{
add(){
console.log('Mixin事件');
}
},
created(){
console.log('Mixin生命周期');
}
});
app.mount('#app');
</script>
</body>
将Mixin直接挂载到Vue实例上。
Vue中就不需要mixins选项了。
注意:一旦使用全局 mixin,它将影响每一个之后创建的组件 (例如,每个子组件)。
三. 插件
plugin插件是把通用功能封装起来,通常向 Vue 添加全局级功能。比如,给Vue添加自定义指令、Mixin等。
3.1.基本用法
下面实例中,声明一个插件并被Vue实例所引用。
<body>
<div id="app">
</div>
<script src="https://unpkg.com/vue@next"></script>
<script>
//对象形式声明插件
const MyPlugin = {
install(app, options) {
console.log('hello world!');
console.log(app);
console.log(options);
}
}
/*
//函数形式声明插件
const MyPlugin = (app, options) => {
console.log('hello world!');
console.log(app);
console.log(options);
}
*/
let app = Vue.createApp({
data() {
return {
}
},
});
app.use(MyPlugin, { name: 'zhangsan' })
app.mount('#app');
</script>
</body>
声明插件可以有两种形式:对象形式、函数形式。
如果是对象形式,那么需要声明 install 方法,并自动给 install 方法传递两个参数。
如果是函数形式,那么直接给此函数传递两个参数。
第一个参数为Vue实例,第二个参数为引用插件时所传递的数据。
使用时,调用Vue实例的use方法引入插件,并给插件传递数据(可选)。
3.2.给Vue扩展功能
下面在插件中给Vue扩展功能。
<body>
<div id="app">
<img src="img/gf01.jpeg" v-imgcir="200">
<p>{
{curdate}}</p>
</div>
<script src="https://unpkg.com/vue@next"></script>
<script>
const MyPlugin = {
install(app, options) {
app.directive('imgcir', {
mounted(el, binding) {
el.style.width = binding.value + 'px';
el.style.height = binding.value + 'px';
el.style.borderRadius = (binding.value / 2) + 'px';
}
});
app.mixin({
data(){
return {
curdate: new Date()
}
}
});
}
}
let app = Vue.createApp({
data() {
return {
}
},
});
app.use(MyPlugin)
app.mount('#app');
</script>
</body>
- 上面代码中,通过插件给Vue扩展了一个自定义标签,一个Mixin。
还没有评论,来说两句吧...