Tricks

# Tricks

[TOC]

# 一、效果实现

# 1.1 懒加载

<ul class="msg-list" @scroll="scrollEvent"></ul>
1
function scrollEvent (e) {
    if (
        e.srcElement.scrollHeight - e.srcElement.scrollTop <=
        e.srcElement.offsetHeight
    ) {
        //加载更多
    }
}
1
2
3
4
5
6
7
8

# 1.2 禁止输入空格

  • .trim修饰符实现
<el-input placeholder="请输入名称" v-model.trim="title" maxlength=30></el-input>
1

# 二、用法进阶

# 2.1 emit传递多个参数

//子组件
this.$emit('refrehData',false,true);

//父组件
<child @refrehData="refrehData(arguments)"></child>

refrehData(data) {
	this.data1= data[0];
	this.data2= data[1];
}
1
2
3
4
5
6
7
8
9
10

# 2.2 打开新窗口

let routeData = this.$router.resolve({
  path: "/about",
  query: {
    name:'lei',
    age: 18,
    phoneNum:12345678901 
  }
});
window.open(routeData.href, '_blank');
1
2
3
4
5
6
7
8
9

# 2.3 计算属性传参

:data="closure(a,b)"

computed: {
	closure() {
		return (a1, b1) => a1+b1
	}
}
1
2
3
4
5
6
7

# 2.4 自定义指令

参考教程:分享8个非常实用的Vue自定义指令 (opens new window)

# 2.4.1 仿element-ui的v-loading指令

Vue.directive('myLoad', {
    // 当被绑定的元素插入到 DOM 中时……
    inserted(el, binding) {
        if (binding.value) {
            //始终设置只有一个加载中弹窗
            let myLoadBg = document.getElementById("yiyu-loading-mark");
            if (myLoadBg) {
                myLoadBg.parentNode.removeChild(myLoadBg)
            }
            let div = document.createElement("div");
            div.setAttribute("id", "yiyu-loading-mark");
            div.innerHTML = `<div class="van-loading van-loading--circular"><span class="van-loading__spinner van-loading__spinner--circular" style="color: rgb(25, 137, 250);"><svg viewBox="25 25 50 50" class="van-loading__circular"><circle cx="50" cy="50" r="20" fill="none"></circle></svg></span></div>`; //你也可以去网上找一些酷炫的加载效果放进去,哈哈哈
            // document.body.appendChild(div);
            el.appendChild(div);
        } else {
            let myLoadBg = document.getElementById("yiyu-loading-mark");
            if (myLoadBg) myLoadBg.parentNode.removeChild(myLoadBg)
        }
    },
    componentUpdated(el, binding) {
        if (binding.value) {
            //始终设置只有一个加载中弹窗
            let myLoadBg = document.getElementById("yiyu-loading-mark");
            if (myLoadBg) {
                myLoadBg.parentNode.removeChild(myLoadBg)
            }
            let div = document.createElement("div");
            div.setAttribute("id", "yiyu-loading-mark");
            div.innerHTML = `<div class="van-loading van-loading--circular"><span class="van-loading__spinner van-loading__spinner--circular" style="color: rgb(25, 137, 250);"><svg viewBox="25 25 50 50" class="van-loading__circular"><circle cx="50" cy="50" r="20" fill="none"></circle></svg></span></div>`;
            el.appendChild(div);
        } else {
            let myLoadBg = document.getElementById("yiyu-loading-mark");
            if (myLoadBg) myLoadBg.parentNode.removeChild(myLoadBg)
        }
    }
})
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

# 2.4.2 动态修改meta.title

//1.在main.js 页面里添加自定义指令
Vue.directive('title', {//单个修改标题
  inserted: function (el, binding) {
    document.title = el.dataset.title
  }
})
//2.在需要修改的页面里添加v-title 指令
<div v-title data-title="我是新的标题"></div>
1
2
3
4
5
6
7
8

# 2.5 重置表单

 this.form = this.$options.data.call(this).form;
1

# 三、性能优化

参考教程:vue性能优化 (opens new window)

# 3.1 computed接收this参数

  • 在组件刷新时重复获取 getter
computed: {
  a () { return 1 },
  b ({ a }) {
      return a + 10
  }
}
1
2
3
4
5
6

# 3.2 Object.freeze()冻结对象

Vue 会通过 Object.defineProperty 对数据进行劫持,来实现视图响应数据的变化,然而有些时候我们的组件就是纯粹的数据展示,不会有任何改变,我们就不需要 Vue 来劫持我们的数据,在大量数据展示的情况下,这能够很明显的减少组件初始化的时间,那如何禁止 Vue 劫持我们的数据呢?可以通过 Object.freeze 方法来冻结一个对象,一旦被冻结的对象就再也不能被修改了。

export default {
  data: () => ({
    users: {}
  }),
  async created() {
    const users = await axios.get("/api/users");
    this.users = Object.freeze(users);
  }
};
1
2
3
4
5
6
7
8
9

# 3.3 第三方插件的按需引入

在项目中经常会需要引入第三方插件,如果我们直接引入整个插件,会导致项目的体积太大,我们可以借助 babel-plugin-component ,然后可以只引入需要的组件,以达到减小项目体积的目的。以下为项目中引入 element-ui 组件库为例: (1)首先,安装 babel-plugin-component

npm install babel-plugin-component -D
1

(2)然后,将 .babelrc 修改为:

{
  "presets": [["es2015", { "modules": false }]],
  "plugins": [
    [
      "component",
      {
        "libraryName": "element-ui",
        "styleLibraryName": "theme-chalk"
      }
    ]
  ]
}
1
2
3
4
5
6
7
8
9
10
11
12

(3)在 main.js 中引入部分组件:

import Vue from 'vue';
import { Button, Select } from 'element-ui';
 Vue.use(Button)
 Vue.use(Select)
1
2
3
4

# 3.4 阻止冒泡事件(点击子级的时候,不触发父级事件)

<van-collapse-item>
    <template #title>
    	<van-checkbox @click.stop.native="() => {}"></van-checkbox>
    </template>
</van-collapse-item>
1
2
3
4
5