vue实现单击选中再次单击取消

使用场景:

当你写一个v-for循环出一个列表,在写一个点击事件,点击之后给一个class,列表某一个颜色突出,在点击取消颜色突出的场景

1.选中赋值的变量不是数组时

-------html
<div 
	:class="['recentOrderBut',recentOrdersArray == item.value ? 'recentOrderActive' : '', ]" 
	v-for="item in recentOrdersDic" 
	:key="item.value" 
	@click="recentOrdersRadioChange(item)" 
	style="user-select: none;">
	{{ item.label }}
</div>

-------js
data(){
	return{
		recentOrdersArray: -1,//不是数组,是一个值
		recentOrdersDic:{
			{
			  label: "不限",
			  value: "",
			},
			{
			  label: "1周内",
			  value: 7,
			},
			{
			  label: "2周内",
			  value: 14,
			},
		}
	}
}
methods:{
	recentOrdersRadioChange(item){
	  if (this.recentOrdersArray == -1) {
        this.recentOrdersArray = item.value;
      } else {
        this.recentOrdersArray = -1;
      }
	}
}

-------css
.recentOrderBut {
  padding: 5px 10px;
  border: 1px solid #909399;
  border-radius: 20px;
  font-size: 13px;
  line-height: 1;
  margin-right: 10px;
  cursor: pointer;
}
.recentOrderActive {
  border: 1px solid #409eff !important;
  color: #fff !important;
  background: #409eff;
}

2.选中赋值的变量是数组时

数组时我没有做,我做的不是数组时,这个数组时是我从网上看的,但是思维是没有错的,如果不行,就用组件的多选,网上有很多

<span v-for="item in subjects" :key="item" :class="{select: item.selected}" @click="changeCss(item)">{{ item.name }}</span>

data() {
  return {
    selectedItem: [],
    author: '微信公众号 haiyan',
    subjects: [
      { name: '历史', selected: false },
      { name: '地理', selected: false },
      { name: '生物', selected: false },
      { name: '政治', selected: false },
      { name: '技术', selected: false },
      { name: '物理', selected: false },
      { name: '化学', selected: false }
    ]
  }
},
changeCss:function (item) {
  if(!item.selected && this.selectedItem.length<3) {//选中状态时点击
    item.selected = true;//变为不选中状态
    this.selectedItem.push(item.name);//更新数组(不选中项)
  } else if(item.selected) {//不选中状态时点击
    item.selected = false;//变为选中状态
    const i = this.selectedItem.indexOf(item.name);//找到当前点击项
    this.selectedItem.splice(i, 1);//移除一个不选中项
  }
}

有用记得点赞,拒绝白嫖,嘻嘻

<think>好的,我现在需要帮助用户解决在Vue中监听全局点击事件的问题。首先,我得回忆一下Vue的事件处理机制。Vue本身主要通过v-on指令来监听DOM事件,但这些都是局部的事件监听,比如在组件内使用@click。但用户的需求是全局的点击事件,这意味着需要在整个应用范围内监听点击,而不仅仅某个组件内部。 接下来,我应该考虑如何实现全局监听。通常,全局事件可以通过在根实例或者使用原生JavaScript的addEventListener来实现。但用户可能使用的是Vue 2或Vue 3,两者的全局事件处理略有不同。比如Vue 3移除了$on、$off等方法,所以需要依赖第三方库如mitt,或者直接使用原生的EventTarget。不过根据用户提供的引用,引用[1]提到Vue3可以使用EventTarget或mitt,而引用[4]中的代码示例使用的是document.onkeydown,这可能是在Vue 2中的做法。因此,我需要分别说明Vue 2和Vue 3的不同方法。 然后,我需要确保回答的结构清晰,分步骤说明。首先介绍原生JavaScript的方法,即在mounted生命周期钩子中添加事件监听,并在beforeDestroy或unmounted中移除,以避免内存泄漏。这一步需要注意Vue 2和Vue 3生命周期钩子的名称变化,比如beforeDestroy变为beforeUnmount。 接着,针对Vue 3的情况,引用[1]提到的mitt库是一个轻量级的事件总线,可以替代Vue 2中的事件总线模式。因此,需要说明如何安装和使用mitt,创建事件总线实例,并在组件中订阅和取消订阅事件。同时,在全局点击时触发自定义事件,比如使用document.addEventListener来触发mitt的事件。 另外,用户提供的引用[4]中的代码示例是监听键盘事件,但原理类似,都是通过document的事件监听来触发方法。因此,可以类比到点击事件的处理,但需要注意事件类型从keydown改为click。 还要考虑事件修饰符的情况,比如用户可能需要在点击外部元素时触发某些操作,这时候可以结合事件对象来判断目标元素是否在组件之外,如引用[3]中提到的在Vue组件中获取全局点击事件的方法。例如,在事件处理函数中检查event.target是否在组件元素之外,从而执行相应的逻辑。 此外,需要注意内存泄漏的问题。在组件销毁时,必须移除事件监听器,否则会导致多次绑定和潜在的错误。这点在Vue 2的beforeDestroy和Vue 3的beforeUnmount钩子中处理。 最后,需要生成相关问题,帮助用户进一步了解相关内容。根据引用中的信息,可以提出关于优化事件监听、第三方库的使用、移除监听的重要性,以及组合键事件监听的问题。 总结来说,回答需要分步骤说明不同版本的Vue如何实现全局点击监听,强调生命周期的管理和内存泄漏的预防,并给出代码示例,同时结合用户提供的引用,确保回答的准确性和实用性。</think>在Vue实现全局点击事件监听,可以通过以下两种方法实现: ### 方法一:原生JavaScript事件监听(推荐) ```javascript // 在Vue组件中 export default { mounted() { // 添加全局点击事件监听 document.addEventListener('click', this.handleGlobalClick) }, beforeDestroy() { // Vue3使用beforeUnmount // 必须移除监听防止内存泄漏 document.removeEventListener('click', this.handleGlobalClick) }, methods: { handleGlobalClick(event) { console.log('全局点击坐标:', event.clientX, event.clientY) // 可在此处添加业务逻辑 } } } ``` ### 方法二:使用事件总线(Vue3推荐) 1. 安装mitt库: ```bash npm install mitt ``` 2. 创建事件总线: ```javascript // eventBus.js import mitt from 'mitt' export const emitter = mitt() ``` 3. 在入口文件注册全局监听: ```javascript // main.js import { emitter } from './eventBus' document.addEventListener('click', (event) => { emitter.emit('global-click', event) }) ``` 4. 组件中使用: ```javascript export default { mounted() { emitter.on('global-click', this.handleClick) }, beforeUnmount() { emitter.off('global-click', this.handleClick) }, methods: { handleClick(event) { console.log('通过事件总线接收点击事件', event) } } } ``` ### 注意事项: 1. **内存管理**:必须及时移除事件监听,否则组件销毁后仍然会执行回调[^1][^3] 2. **事件冲突**:可通过`event.stopPropagation()`阻止事件冒泡 3. **性能优化**:高频点击事件建议添加节流函数 4. **组件外点击检测**:可配合`v-click-outside`指令实现特定区域的点击检测[^3]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值