vue 工作知识总结

https://znasr.gitee.io/mywebsite​​​​​​​

1.优化​​​​​​​ 

//封装按钮 避免用户频繁点击 减少http请求 disable 控制是否可以点击
<template>
  <div>
    <div class="submit-box" @click="submitAction">
      <div
        :class="['submit', ...btnClass, { disable: disable }]"
        :style="{ background: bgColor }"
      >
        <slot name="btnCon">提交</slot>
      </div>
    </div>
  </div>
</template>

<script>
export default {
  name: "submitBtn",
  props: {
    disable: {
      type: Boolean,
      default: false
    },
    btnClass: {
      type: Array,
      default: () => []
    },
    bgColor: {
      type: String,
      default: ""
    }
  },
  data() {
    return {
      time: 0
    };
  },
  methods: {
    submitAction() {
      if (this.disable) return;
      let now = new Date().getTime();
      if (now - this.time > 1000) {
        this.time = new Date().getTime();
        this.$emit("submitAction");
      }
    }
  }
};
</script>

<style scoped lang="less">
@import "../assets/css/main";
.submit-box {
  width: 100%;
  .submit {
    width: 82%;
    height: 1.11rem;
    border-radius: 0.22rem;
    margin: 0 auto;
    background: #b11d2f;
    text-align: center;
    line-height: 1.11rem;
    font-size: 30px;
    font-weight: 400;
    color: #fff;
    border-radius: 40px;
  }
  .disable {
    background: #ddd !important;
  }
}
</style>
// 防止重复提交指令
const preventReClick = Vue.directive('preventReClick', {
  bind(el, binding) {
    el.addEventListener('click', () => {
      if (!el.disabled) {
        el.disabled = true;
        setTimeout(() => {
          el.disabled = false;
        }, binding.value || 2000);
      }
    });
  }
});

export { preventReClick };

import { preventReClick } from './direct';
Vue.use(preventReClick);
//按钮添加指令
<el-button v-prevent-re-click>登录</el-button>
// 防抖 防止用户频繁操作。只执行最后一次函数操作
  throttling(fn, delay) {
    // timer是闭包中的
    let timer = null;
    return (function () {
      if (timer) {
        clearTimeout(timer);
      }
      timer = setTimeout(() => {
        fn.apply(this, arguments);
        timer = null;
      }, delay);
    })();
  }
 //数组去重
  unique(arr, prop) {
    let newArr = [];
    let Arr = [];
    for (var i = 0; i < arr.length; i++) {
      if (!arr[i].value) continue;
      if (newArr.indexOf(arr[i][prop]) == -1) {
        newArr.push(arr[i][prop]);
        Arr.push(arr[i]);
      }
    }
    return Arr;
  },


  /**
   * 对象数组排序
   * @param {*} prop  参数名字
   * @param {*} rev 默认升序 arr.sort((a,b)=>{b-a})
   * @returns arr.sort(sortby('age')) //根据年纪进行排序
   */

  sortby(prop, rev = true) {
    return function (a, b) {
      let val1 = a[prop];
      let val2 = b[prop];
      return rev ? val1 - val2 : val2 - val1;
    };
  },

/**
 * 保留两位整数补零
 * @param n
 * @returns {string}
 */
export function numZero(n) {
  return n < 10 ? "0" + n : "" + n;
}

/**
 * 获取Url的参数
 * @param name
 * @returns {string}
 */
export function getParam(name) {
  const LocString = String(window.document.location.href);
  let rs = new RegExp("(^|)" + name + "=([^&]*)(&|$)", "gi").exec(LocString),
    tmp;
  if (tmp === rs) {
    return tmp[2];
  }
  return "";
}

/**
 * 获取客户端是 Android 还是IOS 还是PC
 * @returns {string}
 */
export function getDeviceType() {
  if (/(iPhone|iPad|iPod|iOS)/i.test(navigator.userAgent)) {
    // 判断iPhone|iPad|iPod|iOS
    return "IOS";
  } else if (/(Android)/i.test(navigator.userAgent)) {
    // 判断Android
    return "Android";
  } else {
    // pc
    return "PC";
  }
}

/**
 * 日期数据格式转换
 * @param time 时间戳
 * @returns {string}
 */
export function fommterDate(time) {
  let date = new Date(time);
  return (
    date.getFullYear() + "/" + (date.getMonth() + 1) + "/" + date.getDate()
  );
}

/**
 * 拼接url后边的参数
 * @param params
 * @returns {string}
 */
export function jsonToStr(params) {
  let str = "";
  for (let i in params) {
    str += "&" + i + "=" + params[i];
  }
  return "?" + str.substring(1);
}

/**
 * 判断是否为微信
 * @returns {boolean}
 */
export function isWechat() {
  var ua = window.navigator.userAgent.toLowerCase();
  if (ua.match(/MicroMessenger/i) == "micromessenger") {
    return true;
  } else {
    return false;
  }
}

制作图标字体网站

IcoMoon App - Icon Font, SVG, PDF & PNG Generator

阿里巴巴图标库

iconfont-阿里巴巴矢量图标库​​​​​​​

使用雪碧图

  1. 将多张图片合并到一张图片中,可以减小图片的总大小。
  2. 将多张图片合并成一张图片后,下载全部所需的资源,只需一次请求。可以减小建立连接的消耗。

2.使用cdn的方式外部加载一些资源,比如vue-router、axios等Vue的周边插件,在webpack.config.js里面,externals里面设置一些不必要打包的外部引用模块。然后在入门文件index.html里面通过cdn的方式引入需要的插件。

Vuex 为什么要分模块并且加命名空间?

模块: 由于使用单一状态树,应用的所有状态会集中到一个比较大的对象。当应用变得非常复杂时,store 对象就有可能会变得相当臃肿。为了解决以上问题,Vuex 允许我们将 store 分割成模块(module)。每个模块拥有自己的 state、mutation、action、getter、甚至是嵌套子模块。

命名空间: 默认情况下,模块内部的 action、mutation、getter是注册在全局命名空间的 --- 这样使得多个模块能够对同一 mutation 或 action 做出响应。如果希望你的模块具有更高的封装度和复用性,你可以通过添加 namespaced:true 的方式使其成为带命名的模块。当模块被注册后,他所有 getter、action、及 mutation 都会自动根据模块注册的路径调整命名。

mixins基础概况

混入 (mixins): 是一种分发 Vue 组件中可复用功能的非常灵活的方式。混入对象可以包含任意组件选项。当组件使用混入对象时,所有混入对象的选项将被混入该组件本身的选项。

举个栗子:

定义一个混入对象

把混入对象混入到当前的组件中 

mixins的特点

1 方法和参数在各组件中不共享

2 值为对象的选项,如methods,components等,选项会被合并,键冲突的组件会覆盖混入对象的

3 混合对象里的钩子函数在组件里的钩子函数之前调用

vue插槽 封装组建经常用到

// 子组建
<template>
  <div class="child">
    // 具名插槽
    <slot name="up"></slot>
    <h3>这里是子组件</h3>
    // 具名插槽
    <slot name="down"></slot>
    // 匿名插槽
    <slot></slot>
  </div>
</template>
<template>
  <div class="father">
    <h3>这里是父组件</h3>
    <child>
      <div class="tmpl" slot="up">
        <span>菜单1</span>
        <span>菜单2</span>
      </div>
      <div class="tmpl" slot="down">
        <span>菜单-1</span>
        <span>菜单-2</span>
      </div>
      <div class="tmpl">
        <span>菜单->1</span>
        <span>菜单->2</span>
      </div>
    </child>
  </div>
</template>


v-if 和 v-for 为什么不建议一起使用

v-for和v-if不要在同一标签中使用,因为解析时先解析v-for在解析v-if。如果遇到需要同时使用时可以考虑写成计算属性的方式。

computed 和 watch 的区别和运用的场景。

computed 是计算属性,依赖其它属性计算值,并且 computed 的值有缓存,职友集当计算值变化才会返回内容,他可以设置getter和setter。

watch 监听到值的变化就会执行回调,在回调中可以进行一系列的操作。

计算属性一般用在模板渲染中,某个值是依赖其它响应对象甚至是计算属性而来;而侦听属性适用于观测某个值的变化去完成一段复杂的业务逻辑。

  • 加载渲染过程
  • 父beforeCreate -> 父created -> 父beforeMount -> 子beforeCreate -> 子created -> 子beforeMount -> 子mounted -> 父mounted
  • 子组件更新过程
  • 父beforeUpdate -> 子beforeUpdate -> 子updated -> 父updated
  • 父组件更新过程
  • 父beforeUpdate -> 父updated
  • 销毁过程
  • 父beforeDestroy -> 子beforeDestroy -> 子destroyed -> 父destroyed
  • 这里只列举针对 Vue 的性能优化,整个项目的性能优化是一个大工程。

  • 对象层级不要过深,否则性能就会差。(数组降纬)
  • 不需要响应式的数据不要放在 data 中(可以使用 Object.freeze() 冻结数据)
  • v-if 和 v-show 区分使用场景
  • computed 和 watch 区分场景使用
  • v-for 遍历必须加 key,key最好是id值,且避免同时使用 v-if
  • 大数据列表和表格性能优化 - 虚拟列表 / 虚拟表格
  • 防止内部泄露,组件销毁后把全局变量和时间销毁
  • 图片懒加载
  • 路由懒加载
  • 异步路由
  • 第三方插件的按需加载
  • 适当采用 keep-alive 缓存组件
  • 防抖、节流的运用
  • 服务端渲染 SSR or 预渲
  • key的讲解
  • Vue2.0 v-for 中 :key 到底有什么用? - 知乎​​​​​​​

vue的双向绑定原理及实现 - ____chen - 博客园

常用的插件

vuex持久化 vuex-persistedstate

lib-flexible/flexible; // 淘宝rem适配方案 移动端

Vue.component("Header", Header); // 自定义组建

@xunlei/vue-lazy-component //组件级懒加载方案

https://github.com/xunleif2e/vue-lazy-component/tree/master/demo

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值