Vue项目中的实用技巧记录

409 阅读4分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第3天,点击查看活动详情

基于工作上Vue项目的一些技巧总结,主观性会比较强,或许对你有帮助。

持续更新中

Composition API的实用技巧

reactivetoRefs配合使用

Vue2中使用data属性声明的变量可以直接使用,在Vue3中如果使用reactive声明响应式对象states,在template模板中需要打点调用属性,如{{ states.name }}

当然你也可以使用展开运算符,返回{ ...states },但这会让属性失去响应性

因此需要toRefs配合使用

<script lang="ts">
import { defineComponent, reactive, toRefs } from "vue";

export default defineComponent({
  setup() {
    const state = reactive({
      label: "hello"
    });
    setTimeout(() => {
      state.label = "111";
    }, 1000);
    return {
      ...toRefs(state)
    };
  }
});
</script>

<template>{{ label }}</template>

此实践技巧仅适合在setup函数中使用

propstoRefs配合使用

和上面的例子差别不大,这里需要注意props中的属性值不要和reacitve中的属性值重名

props需要先声明类型,才可以使用

<script lang="ts">
import { defineComponent, toRefs } from "vue";

export default defineComponent({
  name: "TextComponents",
  props: {
    msg: {
      type: String,
      default: "hello"
    }
  },
  setup(props) {
    return {
      ...toRefs(props)
    };
  }
});
</script>

<template>
  <div>{{ msg }}</div>
</template>

此实践技巧仅适合在setup函数中使用

自动注册Vue全局组件

由于webpackvite注册Vue全局组件的方式不尽相同,因此分开两个版本说明

webpack版本

webpack的环境下,可以使用require.context方法获取所需全局注册的vue组件

require.contextwebpack官网的详细说明

首先在component文件夹新建index.js文件,使用require.context获取vue文件

const componentList = require.context(
  // 其组件目录的相对路径
  '../components',
  // 是否查询其子目录
  true,
  // 匹配vue后缀文件名的文件
  /.vue$/
)

然后使用install方法,vue注册全局组件

需要注意的是组件名称,可以是文件名,也可以是vue文件的name属性

这里以name属性为例,如name:"inputComponent",可以在template这样使用<input-component />

const autoRegist = {
  install(app) {
    componentList.keys().forEach((path) => {
      const file = components(path).default
      const fileName = file.name
      app.component(fileName, file || components(path))
    })
  }
}

export default autoRegist

最后需要在main.js使用

import autoRegist from './components'

app.use(autoRegist)

vite版本

vite中的操作和webpack差不多,也是获取vue文件,然后注册组件

主要用到的方法是import.meta.globglobEager,区别是同步还是异步

详细内容可以到vite官网查看相关信息

异步注册全局组件,需要调用vue中的defineAsyncComponent

import { defineAsyncComponent } from "vue";
const componentList = import.meta.glob("@/components/*.vue");

const autoRegist = {
  install(app) {
    for (const [key, value] of Object.entries(componentList)) {
      const name = key.slice(key.lastIndexOf("/") + 1, key.lastIndexOf("."));
      app.component(name, defineAsyncComponent(value));
    }
  }
};

export default autoRegist;

本次组件名称选择截取文件名称的方法

如文件名是selectComponent,则可以可以在template这样使用<select-component />

同步注册全局组件则需要修改部分内容,如下

const componentList = import.meta.glob("@/components/*.vue");

app.component(name, value);

最后在main.js使用即可

import autoRegist from "./components";

app.use(autoRegist);

自定义指令

判断权限的自定义指令v-permission

Vue3的自定义指令为例

依旧是获取权限数组,根据传入的权限字符串,判断是否移除节点,具体代码如下

import { DirectiveBinding, VNode } from "vue";

const permissionList = ["add", "update"];

export default {
  mounted(el: HTMLElement, binding: DirectiveBinding, vnode: VNode, prevVnode: VNode | null) {
    const isHas = permissionList.includes(binding.value);
    if (!isHas) {
      el.parentNode && el.parentNode.removeChild(el);
    }
  }
};

具体使用如下

<template>
  <div>
    premission
    <div v-permission="'add'">有权限</div>
    <div v-permission="false">无权限</div>
  </div>
</template>

可根据需求优化代码,比如传值必须是字符串,否则有报错提示,可传数组,判断多个权限亦可

自动注册全局自定义指令

基本与自动注册Vue全局组件一样,套路还是获取自定义指令js文件,然后遍历文件,

调用vue注册全局自定义指令即可

vite环境为例

需要注意的是,可能会把index.js文件都获取到,需要把它去除

import { App } from "vue";
const directivesList = import.meta.globEager("@/directives/*.ts");

const autoRegist = {
  install(app: App) {
    for (const [key, value] of Object.entries(directivesList)) {
      const name = key.slice(key.lastIndexOf("/") + 1, key.lastIndexOf("."));
      app.directive(name, value.default);
      console.log(directivesList);
    }
  }
};

export default autoRegist;

main.js文件中使用

import autoRegistDirectives from "./directives";

app.use(autoRegistDirectives);

mixin的使用

如果项目使用Vue2,有大量重复代码,可以考虑使用mixin

建议每个页面只用一个mixin,项目中mixin最好不要超过3个

当项目中有大量的curd页面,可以把重复代码抽离到mixin当中,比如表格数据,翻页相关的数据等

export default {
  data() {
    return {
      tableData: [], // 数据列表
      page: 1, // 当前页码
      limit: 15, // 每页数
      total: 0, // 总条数
      loading: false, // loading状态
      addOrUpdateVisible: false, // 新增/更新弹窗visible状态
    };
  },
  methods: {
    // 分页
    handleChangePage(val) {
      this.page = val;
      this.findPage();
    },
  },
};
<template>
  <div class="home" @click="handleChangePage(1)">
    {{ tableData }}
  </div>
</template>

<script>
import useMixin from "../mixin/useMixin";

export default {
  name: "demo",
  mixins: [useMixin],
  methods: {
    findPage() {
      console.log("findPage");
    },
  },
};
</script>

以上就是mixin的例子,可以在调用的页面,直接调用里面的变量和事件

需要注意的是调用页面与mixin中同名的,会覆盖mixin变量或事件

待更新

参考文章

(23条消息) vue3中自动化注册全局组件vite版_xiexikk的博客-CSDN博客_vite全局组件