【Vue】 通用方法


1. Excel 日期格式化
formatDate(numb, format) {
      const time = new Date((numb - 1) * 24 * 3600000 + 1)
      time.setYear(time.getFullYear() - 70)
      const year = time.getFullYear() + ''
      const month = time.getMonth() + 1 + ''
      const date = time.getDate() - 1 + ''
      if (format && format.length === 1) {
        return year + format + month + format + date
      }
      return year + (month < 10 ? '0' + month : month) + (date < 10 ? '0' + date : date)
}
2. Excel 中文键名转英文键名
 async  success({ header, results }) {
      	// 数据的键都是中文的,要转换成英文才能进行导入
      	// 和新增员工的属性是一致的
        // 定义对应中文的接口属性
        const userRelations = {
          '入职日期': 'timeOfEntry',
          '手机号': 'mobile',
          '姓名': 'username',
          '转正日期': 'correctionTime',
          '工号': 'workNumber'
        }
        let newArr = results.map((item) => {
        // 定义一个空对象来接受转换后的值
        let userInfo = {};
        // 循环里面的 key
        Object.keys(item).forEach((key) => {
          // 现在 key 是中文
          // userRelations[key] 根据中文 key 获取 userRelations 的值,就是接口对应的英文属性
          // item[key] 根据中文的键,找到对应的值,让后给 userInfo 的英文键赋值
          userInfo[userRelations[key]] = item[key];
        });
        // 返回给 map 转换成数组
        return userInfo;
      });
      await importEmployee(arr) // 调用导入接口  接受一个新数组
      this.$message.success("Excel导入成功!");
      this.$router.back() // 返回上一个页面
 }
3. 时间过滤器

4. 数组对象转换树形结构
 let input = [{
      id: 1,
      val: '学校',
      parentId: null
    }, {
      id: 2,
      val: '班级1',
      parentId: 1
    }, {
      id: 3,
      val: '班级2',
      parentId: 1
    }, {
      id: 4,
      val: '学生1',
      parentId: 2
    }, {
      id: 5,
      val: '学生2',
      parentId: 2
    }, {
      id: 6,
      val: '学生3',
      parentId: 3
    }, ]

// 递归方式
function transformTreeList(list, val) {
      // 接受数据的数组
      let arr = []
      list.forEach(item => {
        // 先找到 父节点,parentId 跟父节点的 id 做关联
        if (item.parentId === val) {
          // 调用该方法再执行上面的判断,传父节点的id进行判断是否有子节点
          // children 接受子节点的数据
          const children = transformTreeList(list, item.id)
          item.children = children.length ? children : []
		  // 把子节点的数据追加到数组里面去
          arr.push(item)
        }
      })
      // 将当前父节点下的子节点返回出去
      return arr
}

// 迭代方式
function transformTreeList(list, parentId) {
// 创建一个空对象来存储构建的树形结构
  const tree = {};
  // 创建一个用来存储所有节点的映射表
  const items = {};

  // 遍历原始数组,将每个节点的数据存储到 items 对象中,并初始化 children 属性为空数组
  list.forEach(item => {
    items[item.id] = {...item, children: []};
  });

  // 再次遍历原始数组,构建树形结构
  list.forEach(item => {
    // 如果当前节点是根节点,则直接存储到 tree 对象中
    if (item.parentId === parentId) {
      tree[item.id] = items[item.id];
    } else {
      console.log('items[item.parentId]::: ',items[item.parentId],items[item.id]);
      // items[item.parentId] 引用的是当前节点的父节点的对象
      // 判断当前节点是否有父节点,有则将当前节点添加到父节点的 children 数组中
      if (items[item.parentId]) {
        // items[item.id] 当前节点
        // 操作 items 对象中的数据,同时也改变了 tree 对象中节点的引用
        items[item.parentId].children.push(items[item.id]);
      } else {
        console.log('没有父节点的数据::: ', item);
      }
    }
  });
  console.log('items::: ', items,tree);
    // 返回树形结构中的所有根节点
  return Object.values(tree);
}

// 因为根节点的 id 值是为 null
const ss = filterList(input, null)
console.log(ss);
5. 数组对象转对象树形嵌套
function fn1(list) {
      // 接受数据
      let obj = {}
      list.forEach(item => {
        // parentId 为 false 找到根节点
        if (!item.parentId) {
          // 进行赋值操作
          obj.id = item.id
          obj.val = item.val
          // 根据 根节点的id 找到子节点
          const children = fn2(item.id)
          // 先判断有无数据
          // 给对象的 children 赋值
          obj.children = children.length ? children : []
        }
      })

      // 接收 根节点的id
      function fn2(id) {
        // 接受子节点的数据
        let arr = []
        list.forEach(item => {
          // 相等的话就是根节点对应的子节点
          if (item.parentId === id) {
            // 根据子节点的 id 继续查找节点
            const children = fn2(item.id)
            // 追加到数组里面去
            arr.push({
              id: item.id,
              val: item.val,
              // 判断有无数据,再进行赋值
              children: children.length ? children : []
            })
          }
        })
        // 将 children 数组返回出去
        return arr
      }
      return obj
    }

	// 传递需要转换的数组
    let s1 = fn1(input)
    console.log(s1);
6. 防抖(只执行最后一次)
// 单独使用
data(){
	return {
		timer:null
	}
}

methods:{
	// timer 有值的话就会清空定时器
    // 有值说明还在计时中,再次触发事件的话就会取消,然后重新计时,一直循环,直到执行完毕
    if (this.timer) {
        clearTimeout(this.timer);
    }
    // 简写 有值说明还在计时中,再次触发事件的话就会取消,然后重新计时,一直循环
    this.timer && clearTimeout(this.timer)
      this.timer = setTimeout(async () => {
        console.log('wwwwwwww');
        await saveUserDetailById({
          ...this.userInfo,
          staffPhoto: fileList.length ? fileList[0].url : " ",
        })
        this.$message.success("更新成功")
        // 还原原来的值
        this.timer=null
     }, 500);
}


// 封装使用
/**
 * *****防抖****
 *
 * 在连续的操作中,无论进行了多长时间,
 * 只有某一次的操作后在指定的时间内没有再操作,这一次才被判定有效
 * @param fn
 * @param t
 * @returns {function(...[*]=)}
 * @constructor
 */
export function debounce(fn, t) {
  // 传递了毫秒就用传递的,没有的话默认 300 毫秒
  let delay = t || 300;
  let timer = null;
  //如果这里return箭头函数,则没有this,会向上查找this,找到window
  return function () {
    // 有定时器还在执行的话会清空,重新开始计时
    // 一直触发的话就会一直清空,直到 fn 函数执行完自动清空,才会接着触发
    // if (timer) {
      // clearTimeout(timer);
    // }
    timer && clearTimeout(timer)
    // 给 timer 赋定时器的 id
    // 执行 fn 函数执行完后清空定时器
    // 这里必须改变 this 指向不然指向 window
    timer = setTimeout(() => {
      // 改变 fn 的 this 指向 vue 实例,让方法在注册到 Vue 实例上
      // this 指向改成 当前方法的调用者
      // 不改变 this 指向的话,指向 undefined 就不能调用 vue 实例上数据
      // arguments 是方法传递的所有参数,已数组的形式接受
      fn.apply(this, arguments);
    }, delay);
  }
}

// 调用
//val 是change方法的传的参数
change:Debounce(function(val){
	console.log('防抖了')
},500)

// 发请求使用
//val 是方法的传的参数
btn: debounce(async function (val) {
      const fileList = this.$refs.staffPhoto.fileList;
      await saveUserDetailById({
        ...this.userInfo,
        staffPhoto: fileList.length ? fileList[0].url : " ",
      });
      console.log("防抖了");
}),
7. 节流(等待上次执行完再执行)
// 单独使用
data(){
	return {
		timer:null
	}
}

methods:{
	// timer 有值就 return 说明上一次执行还没成功
      if (this.timer) {
        return;
      }
      this.timer = setTimeout(async () => {
        await saveUserDetailById({
          ...this.userInfo,
          staffPhoto: fileList.length ? fileList[0].url : " ",
        });
        // 执行完毕后重复赋值为 null
        this.timer = null;
        this.$message.success("更新成功");
      }, 500);
}


// 封装使用
/****节流****
     *
     * 一定时间内一定执行而且只执行一次。我们通常规定300ms执行一下的话,
     * 那不管你持续不断的点击,一到300ms就执行一次了。
     * 所以你持续不断的点击足够久的话,那就执行很多次了。
     * @param fn
     * @param delay
     * @returns {function(...[*]=)}
     * @constructor
*/
export function throttle(fn, delay = 500) {
  let canRun = null; // 通过闭包保存一个标记
  // 返回一个方法供调用者使用
  return function () {
    // canRun 有值说明还没执行完,在delay时间内还有执行完,直接返回,不执行fn
    if (canRun) return;
    canRun = setTimeout(() => {
      // this 指向改成 当前方法的调用者
      // 不改变 this 指向的话,默认会指向 window
      // argments 拿到传递的方法的参数
      fn.apply(this, arguments);
      // 执行完后清空,可以执行下一个 fn
      canRun = null
    }, delay);
  };
}

// 调用
btn: throttle(async function (val) {
      const fileList = this.$refs.staffPhoto.fileList;
      await saveUserDetailById({
        ...this.userInfo,
        staffPhoto: fileList.length ? fileList[0].url : " ",
      });
      console.log("节流了");
}),
8. 下载文件 (全局混入)
export default {
  methods: {
    downLoad(url) {
      console.log(url);
      let a = document.createElement("a");
      let evt = document.createEvent("MouseEvents");
      // 下载的名字
      a.download = "1.docx";
      // 下载地址
      a.href = url;
      evt.initEvent("click", true, true);
      a.dispatchEvent(evt);
      window.URL.revokeObjectURL(a.href);
      this.$message.success("操作成功");
    },
  }
}
9. 加载中
// 开启
const loading = this.$loading({
          lock: true,
          text: "正在加载中...请不要关闭此页面",
          spinner: "el-icon-loading",
          background: "rgba(0, 0, 0, 0.7)"
});

// 关闭
loading.close();
10. 图片懒加载指令
lazy: {
    mounted(el) {
      console.log(el);
      let data = el.src
      el.src = ''

      // 观察者:观察当前这个图片是否已经进入到一个可视区域
      // 这个回调函数元素出现和离开可视区域的时候都会触发
      // [{ isIntersecting }] 将这个数组对象里面的 isIntersecting 解构出来
      const observer = new IntersectionObserver(([{ isIntersecting }]) => {
        // console.log('isIntersecting :>> ', isIntersecting);
        // isIntersecting 当前这个参数为 true 说明划到了图片可视区域
        if (isIntersecting) {
          // 加载图片
          el.src = data
          // 停止观察 unobserve(el) 不停止的话他会一直触发这个页面进行观察
          observer.unobserve(el)
        }
      })
      // 使用 observe(el) 方法观察使用指令的 dom
      observer.observe(el)
      console.log(observer);
    }
}
11. 动态注册所有 components 下的组件
// 第一个参数 传文件夹的路径
// 第二个参数 有多层目录的时候希望递归的去查询的话可以设置 true ,一级目录的话 false 就行了
// 第三个参数 匹配规则,正则表达式,匹配对应的文件
// 接受一个方法
const componentsContext = require.context('./components', true, /index.vue$/, 'sync')
console.log(componentsContext.keys());
console.log(componentsContext);
componentsContext.keys().forEach((path) => {
  // key:使用返回的方法接受组件路径,拿到每个组件的实例对象
  // 兼容 import export 和 require module.export 两种规范
  const key = componentsContext(path).default || componentsContext(path)
  // 组件名就是实例对象组件的 name 值,key 组件整个配置对象
  vue.component(key.name, key)
})
vue的常用方法总结 第一章 Vue核心知识讲解 5 第二节 引包、留坑、实例化 、插值表达式{{}} 5 1. 引包 5 2. 留坑 5 3. 实例化 5 4. 插值表达式{{ }} 5 第三节 熟悉及使用常用指令 5 1. 什么是指令 5 2. 常用的指令有哪些,及怎么使用这些指令 6 第四节 阐述vue单双向数据流及事件绑定 6 1. vue单向数据流绑定属性值 v-bind: (属性) 简写 :(属性) 6 2. vue双向数据流 v-model 只作用于有value属性的元素 7 3. 事件绑定v-on:事件名="表达式||函数名" 简写 @事件名="表达式||函数名" 8 4. 总结 8 第五节 过滤器 8 1、过滤器有全局过滤器和组件内的过滤器 应用 {{ msg | 过滤器名}} 8 2、 vue中的this是vue封装好给我们使用的,跟平常方法里面的this是不同的 9 第六节 数据监听watch(深度监听)计算属性computed 9 watch监听单个,computed监听多个 9 总结: 10 第二章 组件化开发知识介绍 11 第一节 组件化开发 11 1、 创建组件的两种方式 11 局部声明 11 2、组件类型(组件开发三步曲:声明、注册、使用 ) 11 第二节 slot插槽和ref、$parent (重点) 11 1、slot插槽 11 2、ref获取子组件实例 12 第三节 父子组件的通信 (核心) 13 1、父传子 14 2、子传父 14 第四节 非父子组件之间的通信 14 简介:建立Bus总线机制实施非父子组件通讯 14 3、回调函数写法 16 第五节 vue的生命周期 17 1、需要频繁的创建和销毁组件 17 2、组件缓存 17 3、成对比较 17 第三章 Vue核心插件之路由模块 18 第一节 路由的跳转原理(哈希模式) 18 1、单页应用的路由模式有两种(哈希模式、history模式) 19 2、 哈希模式原理 19 3、建议的选择:(小D课堂课程) 19 第二节 安装和使用路由 19 第三节 路由的跳转 20 1、路由的跳转方式2种: 20 2、区别: 20 3、vue-router中的对象:$route $router 21 第四节 路由的传参和取参 21 1. 查询参 21 2. 路由参数 21 3、js跳转路由传参和标签传参,路由相同而参数不同时页面不做刷新的问题 22 总结: 22 第五节 嵌套路由(Children) 23 第六节 路由守卫 23 第五章 Vue全家桶各部分核⼼知识详解 24 第1节 构建vue项⽬的利器—脚⼿架vue-cli3 24 1、安装vue-cli3 24 2、创建项⽬ 24 3、 vue.config.js ⼿动在根⽬录新建⼀个vue.config.js⽂件 24 第2节 ⽗⼦组件传值(参考第二章第2、3节) 25 第3节 非⽗⼦组件传值(参考第二章第4节) 25 1. 事件总线(参考第二章第4节) 25 2. $attrs / $listeners 25 3. Vuex (详见第5节) 25 第4节 玩转单⻚⾯应⽤的控制中⼼—vue-router(与第三章基本差不多) 26 梦学谷第137课ElementUI实现页面横向指示导航,比小D课堂的那种写法要好点 26 1、路由的基本配置 26 2、路由的跳转 26 3、动态路由 27 4、嵌套路由 27 5、导航守卫 27 6、路由懒加载 28 第5节 状态管理中⼼—vuex的基础⽤法(官方文档,非常好用) 28  State 28  Mutations 28  Actions 28  vuex⾥包含的基本参数 28  还有别的mapState这些很好用 29 import { mapState, mapMutations } from "vuex";(导入非默认成员) 29 其实是ES6语法,详见梦学谷89课 29 第6节 状态管理中⼼—vuex的⾼级⽤法 29  vuex中的计算属性—Getters 30  模块化概念—Modules 30
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值