# 前言

# ✨魁首

🔔一个没有天赋的前端程序员👨‍💻 💡博客

# 🔰关注我

🤖Github |🔑CSDN | 💎掘金 | 📖 知乎 | 💡博客 |

# 一、用 A-Z 表示 el-table 表格序号,一个你可能忽略的方法

业务场景:基于element UI 15.6版本,el-table 表格的序号我想用 A-Z 该怎么表示呢?

需求分析:这里可以用的方法 String.fromCharCode(), 看看MDN怎么解释的!

功能实现在线远行

image.png

在 UTF-16 中,绝大部分常用的字符可以用一个 16 位的值表示(即一个代码单元)。然而,有一类字符叫 Base Multilingual Plane (BMP),是所有可寻址的 Unicode 码点的 1/17th。剩下的码点,从范围 65536 (0x010000) 到 1114111 (0x10FFFF) 被称之为补充字符。在 UTF-16 中,补充字符也叫代理(surrogates),用两个 16 位代码单元表示,它是有目的被保留下来的。两个代理(surrogates)形成一个有效组合,也叫代理对,可以用来表示一个补充字符。

因为 fromCharCode() 只作用于 16 位的值 (跟 \u 转义序列一样),为了返回一个补充字符,一个代理对是必须的。例如,String.fromCharCode(0xD83C, 0xDF03) 和 \uD83C\uDF03 返回码点 U+1F303 "Night with Stars"。

示例

String.fromCharCode(65, 66, 67);   // 返回 "ABC"
String.fromCharCode(0x2014);       // 返回 "—"
String.fromCharCode(0x12014);      // 也是返回 "—"; 数字 1 被剔除并忽略
String.fromCharCode(8212);         // 也是返回 "—"; 8212 是 0x2014 的十进制表示

String.fromCharCode(0xD83C, 0xDF03); // Code Point U+1F303 "Night with
String.fromCharCode(55356, 57091);   // Stars" == "\uD83C\uDF03"
String.fromCharCode(0xD834, 0xDF06, 0x61, 0xD834, 0xDF07); // "\uD834\uDF06a\uD834\uDF07"
1
2
3
4
5
6
7
8
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>A-Z 表示 el-table 表格序号</title>
    <script src="https://unpkg.com/vue@2"></script>
    <script src="https://unpkg.com/element-ui@2.15.6/lib/index.js"></script>
    <link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css"/>
  </head>
  <body>
    <div id="app">
      <el-table :data="listArr" style="width: 100%;" border height="393">
        <el-table-column type="selection"></el-table-column>
        <el-table-column prop="id" label="ID"></el-table-column>
        <el-table-column prop="name" label="姓名"></el-table-column>
        <el-table-column prop="age" label="年龄"></el-table-column>
      </el-table>
    </div>
    <script>
      new Vue({
        el: "#app",
        data: {
          listArr: [
            { id: 1, name: "周一", age: 11 },
            { id: 2, name: "虎二", age: 12 },
            { id: 3, name: "张三", age: 13 },
            { id: 4, name: "李四", age: 14 },
            { id: 5, name: "王五", age: 15 },
            { id: 6, name: "赵六", age: 16 }
          ]
        },
        created() {
          this.listArr.forEach((item, index) => {
            // 返回由指定的 UTF-16 代码单元序列创建的字符串作为 ID
            item.id = String.fromCharCode(65 + index);
          });
          console.log(this.listArr);
        }
      });
    </script>
  </body>
</html>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42

# 二、Transform 穿梭框 组件重写,实现多列穿梭

官方组件: image.png

重写后:在线远行

Transform穿梭框.gif

业务场景:基于element UI 15.6版本,Transform 穿梭框 里穿梭内容只有一列勾选内容,能不能展示多列,以表格的形式进行勾选呢?

需求分析:其实重头实现一个穿梭效果也不难,在el-table 表格的基础上,中间两个按钮的点击事件来动态改变左右两边表格的数据;

功能实现

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>Transform 多列穿梭框 </title>
    <script src="https://unpkg.com/vue@2"></script>
    <script src="https://unpkg.com/element-ui@2.15.6/lib/index.js"></script>
    <link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css"/>
  </head>
  <body>
    <div id="dynamic-component-demo">
      <div style="width: 900px;">
        <el-form>
          <el-row style="display: flex;">
            <el-col :span="10" style="width: 390px; border: 1px solid #ebeef5;">
              <div style="padding: 5px 15px 10px; background-color: #f5f7fa; border-radius: 3px;">
                <el-form-item label="未选列表">
                  <span style="float: right;">{{ listArr.length }}</span>
                  <el-table :data="listArr" style="width: 100%;" border height="393" @selection-change="checkAll">
                    <el-table-column type="selection"></el-table-column>
                    <el-table-column prop="id" label="ID"></el-table-column>
                    <el-table-column prop="name" label="姓名"></el-table-column>
                    <el-table-column prop="age" label="年龄"></el-table-column>
                  </el-table>
                </el-form-item>
              </div>
            </el-col>
            <el-col :span="3" style="width: 80px; padding: 0 10px; display: flex; flex-direction: column; justify-content: center; ">
               <!--穿梭框选中-->
              <div style="display: flex; justify-content: center;">
                <el-button class="middle-circle" icon="el-icon-arrow-right" :disabled="!leftData.length" size="mini" type="primary" @click="handelSelect" />
              </div>
              <!--穿梭框取消-->
              <div style="display: flex; justify-content: center;">
                <el-button class="middle-circle" icon="el-icon-arrow-left" :disabled="!rightData.length" size="mini" type="primary" style="margin-top: 10px; margin-left: 0px;" click="handleRemoveSelect" />
              </div>
            </el-col>
            <el-col :span="10" style="width: 390px; border: 1px solid #ebeef5;">
              <div style="padding: 5px 15px 10px; background-color: #f5f7fa; border-radius: 3px;">
                <el-form-item label="已选列表">
                  <span style="float: right;">{{ selectArr.length }}</span>
                  <el-table :data="selectArr" style="width: 100%;" border height="393" selection-change="checkRightAll">
                    <el-table-column type="selection"></el-table-column>
                    <el-table-column prop="id" label="ID"></el-table-column>
                    <el-table-column prop="name" label="姓名"></el-table-column>
                    <el-table-column prop="age" label="年龄"></el-table-column>
                  </el-table>
                </el-form-item>
              </div>
            </el-col>
          </el-row>
        </el-form>
      </div>
    </div>

    <script>
      new Vue({
        el: "#dynamic-component-demo",
        data: {
          searchParam: {},
          listArr: [
            { id: 1, name: "AAA", age: 1 },
            { id: 2, name: "BBB", age: 1 },
            { id: 3, name: "CCC", age: 1 },
            { id: 4, name: "DDD", age: 1 },
            { id: 5, name: "EEE", age: 1 },
            { id: 6, name: "FFF", age: 1 }
          ],
          selectArr: [],
          changeArr: [],
          leftData: [], // 左边选中列表数据
          rightData: [] // 右边选中列表数据
        },
        methods: {
          checkAll(val) {
            this.leftData = val;
          },
          checkRightAll(val) {
            this.rightData = val;
          },
          // 穿梭框选中
          handelSelect() {
            for (let i = 0; i < this.selectArr.length; i++) {
              for (let j = 0; j < this.leftData.length; j++) {
                if (this.leftData[j].id === this.selectArr[i].id) {
                  this.leftData = []; // 避免 左边勾选内容 leftData 与 右边内容 selectArr 重复
                }
              }
            }
            this.selectArr = this.handleConcatArr(
              this.selectArr,
              this.leftData
            );
            this.handleRemoveTabList(this.leftData, this.listArr);
            this.leftData = [];
          },
          // 穿梭框取消
          handleRemoveSelect() {
            this.listArr = this.handleConcatArr(this.listArr, this.rightData);
            this.handleRemoveTabList(this.rightData, this.selectArr);
            this.rightData = [];
          },
          handleConcatArr(selectArr, leftData) {
            let arr = [];
            arr = arr.concat(selectArr, leftData);
            return arr;
          },
          handleRemoveTabList(isNeedArr, originalArr) {
            if (isNeedArr.length && originalArr.length) {
              for (let i = 0; i < isNeedArr.length; i++) {
                for (let k = 0; k < originalArr.length; k++) {
                  if (isNeedArr[i]["id"] === originalArr[k]["id"]) {
                    originalArr.splice(k, 1);
                  }
                }
              }
            }
          }
        }
      });
    </script>
  </body>
</html>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124

# 三、虚拟列表实现 el-table 表格内的无限滚动

业务场景:项目基于element UI 15.6版本在 el-table 表格中,一个有着700条的数据,加载时间很慢,不能使用分页,实现滚动时按动态加载数据;

需求分析:结合 el-table 表格 和 InfiniteScroll 无限滚动组件,初始化表格加载可见区域内的数据,通过监听虚拟列表滚动的位置,动态改变请求翻页参数,从而达到动态加载的效果。

功能实现

<template>
    <el-input v-model="searchParam.id" clearable :title="searchParam.id" />
    <el-input v-model="searchParam.name" clearable :title="searchParam.name" />
    <el-table :data="taskData" v-loading="taskLoading" v-el-table-infinite-scroll="toLoadMore" 
              infinite-scroll-disabled="scrollDisabled" infinite-scroll-immediate="false">
            <el-table-column label="id" prop="ID" show-overflow-tooltip />
            <el-table-column label="name" prop="Name" show-overflow-tooltip />
            <el-table-column label="sex" prop="Sex" show-overflow-tooltip />
            <el-table-column label="age" prop="Age" show-overflow-tooltip />
    </el-table>
</template>

<script>
    import elTableInfiniteScroll from 'el-table-infinite-scroll';
    export default {
      directives: {
        'el-table-infinite-scroll': elTableInfiniteScroll
      },
      data() {
        return {
          taskData: [],
          taskLoading: false,
          scrollDisabled: false,
          searchParam: {
            page_size: 10,
            page_no: 1
          },
        }
      },
      created() {
        this.toGetList();
      },
      methods: {
         toGetList() {
              this.searchParam.page_no = 1; // 初始化 搜索条件 页码
              const param = {};
              Object.keys(this.searchParam).forEach((item) => {
                if (this.searchParam[item] || this.searchParam[item] === 0) {
                  param[item] = this.searchParam[item];
                }
              });
              this.scrollDisabled = true;
              this.taskData = []; // 搜索前清空滚动加载获取的数据,避免内容重复
              this.loadList(param);
        },
        toLoadMore() {
          // 监听表格滚动事件
          this.searchParam.page_no++;
          const param = {};
          Object.keys(this.searchParam).forEach((item) => {
            if (this.searchParam[item] || this.searchParam[item] === 0) {
              param[item] = this.searchParam[item];
            }
          });
          this.loadList(param);
        },
        loadList(param) {
          this.taskLoading = true;
          getList(param).then((res) => {
            this.taskLoading = false;
            // 没数据的时候,禁用 infinite-scroll-disabled 滚动事件
            if (res.length === 0) return (this.scrollDisabled = true);
            this.scrollDisabled = false;
            this.taskData.push(...res); // 分页请求的数据,追加到任务列表中
          });
        },
      }
    }
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69

# 四、element Switch开关开启时触发click事件,关闭时不触发

思路:change中提供了参数val,可以根据当前点击的状态true/false来判断当前开启/关闭的状态 image.png 代码: 在线运行

<template>
    <el-switch
        v-model="value"
        :active-text="value? '是' : '否'"
        @change="changeIsNeedHint"
    >
    </el-switch>
</template>

<script>
    data() {
      return {
        value: true
      }
    },
    methods: {
      changeIsNeedHint(val){
        if(val === false) return false; // 如果当前状态为关闭,则不提示
        this.$confirm(`你触发了click事件`, "提示", {
          confirmButtonText: "我知道了",
          cancelButtonText: "取消",
          type: "warning",
        }).then(() => {
          // 点击 我知道了 之后的提示
          this.$message({
             type: "success",
             message: "已触发click"
           })
        }).catch(() => {
          // 点击 取消 之后的提示
          this.$message({
             type: "info",
             message: "已取消操作"
           })
        })
      }
    }
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38

# 五、elementUI 两个Switch 开关能不能实现相互依赖?

思路:通过change点击事件,value1开关 监听 value2开关的value值,来实现项目依赖的效果!

image.png

代码在线运行

<template>
    <el-switch
          v-model="value1"
          :active-value="'day'" 
          :inactive-value="'weekly'"
          :active-text="value1 === 'day' ? '每日' : '每周'"
          @change="handleFrequency"
      >
    </el-switch> <br/>

    <el-switch
          v-model="value2"
          :active-value="true"
          :inactive-value="false"
          :active-text="value2 ? '是' : '否'"
          @change="handleFirm"
      >
    </el-switch>
</template>

<script>
    data() {
      return {
        value1: 'day', // 开启关闭除了可以传true/false, 还可以这样传
        value2: true
      }
    },
    methods: {
      handleFrequency(){// 按钮2在按钮1关闭状态下,才可改动
        if(this.value2 === true) this.value1 = 'day';
      },
      handleFirm(){ // 按钮2打开后,按钮1自动打开
        this.value1 = 'day'
      },
    }
</script>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37

# 六、使用cookie,让MessageBox 弹框一天内不再弹出

业务场景:基于element UI 15.6版本,MessageBox 弹框 点击一个按钮后,固定时间内不再弹出能不能实现?

需求分析:这个时候就需要用到我们浏览器的 Cookie 了,当点击按钮后,将一天后的时间存入到 cookie 中,第二次打开时,会首先判断一下当前的时间是否到了 cookie 中保存的时间,如果没到,则不用弹出!

功能实现在线远行

image.png

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>MessageBox 弹框一天内不再弹出</title>
    <script src="https://unpkg.com/vue@2"></script>
    <script src="https://unpkg.com/element-ui@2.15.6/lib/index.js"></script>
    <script src="https://cdn.bootcss.com/moment.js/2.24.0/moment.min.js"></script>
    <script src="https://cdn.bootcss.com/moment.js/2.24.0/locale/zh-cn.js"></script>
    <link
      rel="stylesheet"
      href="https://unpkg.com/element-ui/lib/theme-chalk/index.css"
    />
  </head>
  <body>
    <div id="dynamic-component-demo">
      <el-button size="small" type="primary" @click="oneClickFirmOffer"
        >按钮</el-button
      >
    </div>

    <script>
      new Vue({
        el: "#dynamic-component-demo",
        data: {
          searchParam: {}
        },
        methods: {
          oneClickFirmOffer() {
            // 判断当前时间是否到了 cookie 中保存的时刻
            if (
              this.getCookie("popped") <
              moment(new Date()).format("YYYY-MM-DD HH:mm:ss")
            ) {
              this.$confirm("这是一个弹窗", "提示", {
                confirmButtonText: "朕已阅",
                cancelButtonText: "一天内不再提示",
                confirmButtonClass: "confirmButton",
                cancelButtonClass: "cancelButton",
                type: "warning"
              })
                .then(() => {})
                .catch(() => {
                  // 将一天后的时刻存入 cookie ,下次访问时不会再弹出
                  let oneDayLater = moment(new Date()).add(1, "d").format("YYYY-MM-DD HH:mm:ss");
                  document.cookie = "popped = yes";
                });
            }
          },
          // 获取Cookie
          getCookie(Name) {
            var search = Name + "=";
            var returnValue = "";
            console.log(Name);
            if (document.cookie.length > 0) {
              console.log(document.cookie.length);
              var offset = document.cookie.indexOf(search);
              if (offset !== -1) {
                offset += search.length;
                var end = document.cookie.indexOf(";", offset);
                if (end == -1) {
                  end = document.cookie.length;
                }
                returnValue = decodeURIComponent(
                  document.cookie.substring(offset, end)
                );
              }
            }
            return returnValue;
          }
        }
      });
    </script>
  </body>
</html>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
最后更新时间: 6/20/2022, 10:48:50 PM