Vue3+ElementPlus—高效存储和回显多选项的状态值

应用场景

监控摄像头,多通道,如通道1,通道2,通道3,通道4,通道5,通道6。

一个属性值,用来表示拥有哪几个通道

每个通道作为一个复选框,使用 位运算 来高效地处理多选框的状态

应用逻辑

使用位运算来高效地处理多选框的状态。在计算机科学中,2 的幂次方在二进制表示中各自占据不同的位: 通道1的值:十进制是1,二进制是 000001 通道2的值:十进制是2,二进制是 000010 通道3的值:十进制是4,二进制是 000100 通道4的值:十进制是8,二进制是 001000 通道5的值:十进制是16,二进制是 010000 通道6的值:十进制是32,二进制是 100000

这种设计的优势:

  • 可以通过简单的加法或按位或运算组合多个通道的值
  • 可以通过按位与运算快速判断某个通道是否被选中
  • 节省存储空间,一个整数就可以表示所有通道的选择状态
  • 位运算天然避免重复值的影响

例如,如果选中了通道1、3和5,那么总值就是 1 + 4 + 16 = 21。要检查通道3是否被选中,只需要检查 21 & 4 是否等于 4。

前置知识

reduce函数

是 JavaScript 数组的一个高阶函数方法,用于对数组中的每个元素执行一个回调函数,并将数组缩减为一个单一的值。

基本语法:

js 复制代码
array.reduce(callback(accumulator, currentValue, currentIndex, array), initialValue)
//或
array.reduce((accumulator, currentValue, currentIndex, array) => {}, initialValue)

参数说明:

  • callback: 执行数组中每个元素的函数,包含以下参数:
    • accumulator:上一次调用回调函数返回的值,或者是提供的初始值
    • currentValue:当前正在处理的数组元素
    • currentIndex(可选):当前处理元素的索引
    • array(可选):调用 reduce 的数组
  • initialValue(可选):作为第一次调用 callback 函数时的第一个参数的值

示例演示:

js 复制代码
// 数组内每个元素相加得到的结果(可以遍历相加,此处是使用reduce函数和位或运算得到结果)
const videoChannelList = [1,4,16]
const value = videoChannelList.reduce((accumulator, currentValue) => accumulator | currentValue, 0);

这里的工作原理是:

  1. 初始值为 0
  2. 对于数组中的每个值,执行按位或运算(|)
  3. 逐步累积结果,最终得到一个合并值

例如:如果选中了通道1(1)、通道3(4)和通道5(16):

  • 第一次:0 | 1 = 1
  • 第二次:1 | 4 = 5
  • 第三次:5 | 16 = 21
  • 最终结果:21

这种方式利用了位运算的特性,每个通道值都是2的幂次方,在二进制中只有一个位为1,通过按位或运算可以安全地合并这些值。

Math.pow()函数

是 JavaScript 中用于计算幂运算的内置函数。

基本语法:

js 复制代码
Math.pow(base, exponent)

参数说明:

  • base:底数
  • exponent:指数

返回值:

返回 base 的 exponent 次幂,即 base^exponent。

例如:

js 复制代码
Math.pow(2, 3)  // 返回 8 (2的3次方)
Math.pow(4, 0.5) // 返回 2 (4的平方根)
Math.pow(10, -1) // 返回 0.1 (10的负一次方)

const bitValue = 1 << i; : 使用位移运算符计算2的i次方

功能:

  • 1 << i 表示将数字1的二进制向左移动i位
  • 等价于计算 Math.pow(2, i) 或 2^i
  • 用于生成二进制中只有第i位为1的数值

示例演示:

html 复制代码
<el-checkbox v-for="item in 6" :label="Math.pow(2, item - 1)" :key="item">
  通道{{item}}
</el-checkbox>

具体生成的值为:

  • 当 item=1 时,Math.pow(2, 0) = 1
  • 当 item=2 时,Math.pow(2, 1) = 2
  • 当 item=3 时,Math.pow(2, 2) = 4
  • 当 item=4 时,Math.pow(2, 3) = 8
  • 当 item=5 时,Math.pow(2, 4) = 16
  • 当 item=6 时,Math.pow(2, 5) = 32

可以通过按位或运算 (|) 安全地合并 可以通过按位与运算 (&) 检查某个位是否被设置 这种方式常用于权限系统或状态标记,因为它能高效地组合和检查多个标志位。

应用实操

xxx.vue

html 复制代码
<template>
...
    <el-form-item label="视频通道" prop="videoChannel">
        <el-checkbox-group v-model="videoChannelList">
            <!--
                这里会生成 6 个复选框,每个复选框的 label 值分别是:
                当 item=1 时,label=Math.pow(2, 0) = 1
                当 item=2 时,label=Math.pow(2, 1) = 2
                当 item=3 时,label=Math.pow(2, 2) = 4
                当 item=4 时,label=Math.pow(2, 3) = 8
                当 item=5 时,label=Math.pow(2, 4) = 16
                当 item=6 时,label=Math.pow(2, 5) = 32
            -->
            <el-checkbox v-for="item in 6" :label="Math.pow(2, item - 1)" :key="item" @change="handleCheckChange('video')">
                通道{{item}}
        </el-checkbox>
        </el-checkbox-group>
    </el-form-item>
	<el-button @click="selectValueFun">取值({{result}})</el-button>
    <el-button @click="echoFun">回显</el-button>
</template>

<script setup>
import { ref } from "vue";
// 被勾选的一个或多个复选框返回数组,如勾选通道1、通道3和通道5,返回的数组是[1,4,16]
const videoChannelList = ref([])
const channelValue = 21
const result = ref(0)
// 回显哪些复选框被选中
const echoFun = () => {
  //视频通道打钩
  for (let i = 0; i < 6; i++) {
    /*
    表示将数字1的二进制向左移动i位
      -等价于计算 Math.pow(2, i) 或 2^i(2的i次幂)
      -用于生成二进制中只有第i位为1的数值
    */
    const bitValue = 1 << i;
    if ((channelValue & bitValue) !== 0) {
      videoChannelList.value.push(bitValue);
    }
  }
}
// 选中一个或多个复选框后的值
const selectValueFun = () => {
  // channel初始值为 0,并与当前值val(遍历数组中的每个值),执行按位或运算(|),获取最终的值(相当于每个元素值相加后的结果,但仅限于元素值为2^i时)
  const value = videoChannelList.value.reduce((channel, val) => channel | val, 0);
  result.value = value;
}
</script>
相关推荐
Sheldon一蓑烟雨任平生6 小时前
Vue3 插件(可选独立模块复用)
vue.js·vue3·插件·vue3 插件·可选独立模块·插件使用方式·插件中的依赖注入
鱼与宇7 小时前
苍穹外卖-VUE
前端·javascript·vue.js
用户47949283569157 小时前
Safari 中文输入法的诡异 Bug:为什么输入 @ 会变成 @@? ## 开头 做 @ 提及功能的时候,测试同学用 Safari 测出了个奇怪的问题
前端·javascript·浏览器
裴嘉靖8 小时前
Vue 生成 PDF 完整教程
前端·vue.js·pdf
毕设小屋vx ylw2824268 小时前
Java开发、Java Web应用、前端技术及Vue项目
java·前端·vue.js
冴羽9 小时前
今日苹果 App Store 前端源码泄露,赶紧 fork 一份看看
前端·javascript·typescript
蒜香拿铁9 小时前
Angular【router路由】
前端·javascript·angular.js
时间的情敌9 小时前
Vite 大型项目优化方案
vue.js
西洼工作室9 小时前
高效管理搜索历史:Vue持久化实践
前端·javascript·vue.js
樱花开了几轉9 小时前
element ui下拉框踩坑
开发语言·javascript·ui