尝试用自定义指令实现以下方法
一. 首先显示模板
<template>
<div class="navBar" >
<div @click="changeIndex(index)" v-for="(item, index) in list" :class="['item']">{{ item }}</div>
</div>
</template>
<script setup>
import { reactive, toRefs, toRef } from "vue";
let state = reactive({
curIndex: 0,
list: ['选项1', '选项2', '选项3', '选项4'
]
})
let { list } = toRefs(state)
let curIndex = toRef(state, 'curIndex')
let changeIndex = (index) => {
//点击改变当前下标
curIndex.value = index
}
</script>
<style>
.navBar {
margin: 0 auto;
width: 400px;
height: 100px;
display: flex;
}
.item {
width: 100px;
border: 1px solid red;
line-height: 100px;
text-align: center;
}
.active {
background-color: pink;
}
</style>
二.用插件的形式准备注册一个自定义指令
参考文档:插件 | Vue.js
他会执行install方式,把app实例传进来,这时候可以在app上挂载一些实例了,这时候顺便在main.js中注册先
三.注册一个全局自定义指令
参考文档:自定义指令 | Vue.js
export default {
install(app) {
app.directive('clickAndAddClass', {
})
}
}
添加上代码
export default {
install(app) {
app.directive('clickAndAddClass', {
mounted(el, binding) {
//拿到自定义指令传过来的配置项
const option = binding.value
//拿到child
const child = el.getElementsByClassName(option.className)
//点击谁,就把最新的下标传进来,并且添加上active类名
child[option.curIndex].className += ` ${option.avtiveClass}`
},
// 在绑定元素的父组件
// 及他自己的所有子节点都更新后调用
updated(el, binding) {
const option = binding.value
//获取旧的配置项
const oldOption = binding.oldValue
const child = el.getElementsByClassName(option.className)
//把上一个item的类名还原
child[oldOption.curIndex].className = oldOption.className
//再把新的item添加上active,记得别忘了不加空格
child[option.curIndex].className += ` ${option.avtiveClass}`
},
})
}
}
四.传入自定义指令的配置项
<template>
<div class="navBar" v-clickAndAddClass="{
curIndex,
avtiveClass: 'active',
className: 'item'
}">
<div @click="changeIndex(index)" v-for="(item, index) in list" :class="['item']">{{ item }}</div>
</div>
</template>
搞定