Vue3.2.x中的小技巧及注意事项总结

 更新时间:2022年04月28日 17:02:47   作者:VELOMA  
Vue是一套用于构建用户界面的渐进式JavaScript框架,是目前最火的前端框架之一,是前端工程师的必备技能,下面这篇文章主要给大家介绍了关于Vue3.2.x中的小技巧及注意事项的相关资料,需要的朋友可以参考下

前言

vue3在2022年的2月7号成为了vue默认版本,并且随之而来的还有vue3的新文档, 并且从实际使用的角度来说, vue3确实比vue2使用起来更加的舒服,所以觉得经过一段时间的使用,来分享一下使用过程中的小技巧以及注意事项。

小技巧

关于减少.value的使用

  • 使用watch来监听Ref数据的时候, 可以做到省略.value的使用, 例如:

      const value = ref(1);
      // 省略() => value.value
      watch(value, (v) => {
        // 省略v.value
        console.log(v);
      }, { immediate: true });
    
      setTimeout(() => {
        value.value = 2;
      }, 1000);
  • 使用vue3.2.25以上版本提供的$ref, 还是跟上面的代码实现一样的功能

    该功能是一个实验性能, 需要相应的配置, 这里以vite为例, 需要在vite.config.ts的vue plugin中添加一个reactivityTransform属性, 请看下面的配置。如果用的是其他工程化工具, 可以参考vue的新文档, 文档中有详细的说明。

      plugins: [
        vue({
          reactivityTransform: true,
        })
      ]
      const count = $ref(1);
      // 增加了() => count
      watch(
        () => count,
        (v) => {
          console.log(v);
        },
        { immediate: true }
      );
    
      setTimeout(() => {
        // 省略了count.value
        count++;
      }, 1000);

输出:

这里需要说明一下使用$ref需要注意的问题, 首先该功能是一个实验性性能, 需要相应的配置, 并且vue的文档中指出该方法是一个编译器宏使用时无需引入, 但为了ts和编辑器的无端报错, 个人还是喜欢显示的引入, 就像这样import { $ref } from 'vue/macros'接着再说一下$ref的另一个很严重的问题, 就是丢失响应式, 为什么会丢失响应式呢? 其实这部分官方文档已经做出了说明, 请看下面的代码

// App.vue
import { $ref } from "vue/macros";
import { useApp } from "./App";
let count = $ref(1);

useApp(count);

setTimeout(() => {
  console.log("change");
  count++;
}, 1500);

// App.ts
import { watch } from "vue";
export const useApp = (count) => {
  watch(
    () => count,
    (c) => {
      console.log("watch", c);
    },
    { immediate: true }
  );
};

上面代码中App.ts里面的watch只会执行一次, 很明显, count丢失了响应性
如何解决这个问题呢?请看下面的代码:

// App.vue
import { $ref, $$ } from "vue/macros"; // 引入$$
import { useApp } from "./App";
let count = $ref(1);

useApp($$(count)); // useApp(count) --> useApp($$(count))

setTimeout(() => {
  console.log("change");
  count++;
}, 1500);

// App.ts
import { watch } from "vue";
export const useApp = (count) => {
  watch(
    count, // () => count --> count
    (c) => {
      console.log("watch", c);
    },
    { immediate: true }
  );
};

可以看到, 我们在传递$ref值的时候 需要用一个$$方法包裹一下, 这样就不会丢失响应性了, 具体更详细的使用方法, 还是希望大家仔细阅读一下vue的新文档

关于减少import导入语句

发现这个功能是无意间的,在使用element-plus的时候, 查看elment-plus官网 指南 快速开始, 其中提到了自动导入的功能, 文档中说的是 首先下载对应的插件npm install -D unplugin-vue-components unplugin-auto-import, 然后如果使用的是vite的话, 需要在vite.config中添加几条配置, 就像下面一样:

// vite.config.ts
import AutoImport from 'unplugin-auto-import/vite'
import Components from 'unplugin-vue-components/vite'
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'

export default {
  plugins: [
    // ...
    AutoImport({
      resolvers: [ElementPlusResolver()],
    }),
    Components({
      resolvers: [ElementPlusResolver()],
    }),
  ],
}

因为好奇去看了这两个包的介绍, 发现不光可以自动导入组件, 还可以自动导入方法, 例如心细的小伙伴已经发现, .value那部分的代码 不管是ref还是$ref我都没有写import语句来导入, 这里就用到了这两个插件, 我们来看一下如果要自动导入vue的方法对应的配置。

// vite.config.ts
import AutoImport from 'unplugin-auto-import/vite'
import Components from 'unplugin-vue-components/vite'
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'

export default {
  plugins: [
    // ...
    AutoImport({
      imports: ["vue", "vue/macros"],  // 增加这一行代码
      resolvers: [ElementPlusResolver()],
    }),
    Components({
      resolvers: [ElementPlusResolver()],
    }),
  ],
}

在这样的配置下就可以愉快的减少import导入了。

关于在script setup中声明组件名字

在script setup的方式刚发布的时候, 我就一直在纠结这个问题, 因为项目中有很多的递归组件, 如果没有name来做标识的话, 势必会产生问题

  • 刚开始vue的issues中其他用户提出的解决方式是在.vue文件中定义两个script标签, 其中一个用来定义组件的name, 而另一个用来编写组件逻辑, 例如下面这样:

这种方式相信对于一些有强迫症或者完美主义者来说是完全不能接受的, 包括我 也不能接受, 所以在vue的issues中就有一个用户开发了一个插件来解决这个问题。

  • unplugin-vue-define-options插件

下载插件npm i unplugin-vue-define-options -D我们直接来看一下这个插件的使用方式:

在vite中使用

// vite.config.ts
import DefineOptions from 'unplugin-vue-define-options/vite'
import Vue from '@vitejs/plugin-vue'

export default defineConfig({
  plugins: [Vue(), DefineOptions()],
})

ts项目需要在tsconfig.json中添加一个配置

{
  "compilerOptions": {
    "types": ["unplugin-vue-define-options"]
  }
}

使用方式

<script setup lang="ts">
  defineOptions({
    name: 'App'
  })
</script>

该插件的功能远远不止定义组件的name, 还可以定义组件的props、emits、render等,有兴趣的小伙伴可以去看一下,感觉可以利用这一特性才做一些骚操作,不过尤大大觉得这种方式不太好。

注意事项

关于响应式的问题

  • props不能使用解构的方式来使用, 例如下面的例子
  // Parent.vue
  <template>
    <ChildVue ref="childRef" v-bind="data" />
  </template>
  
  <script setup lang="ts">
    import { reactive } from 'vue';
    import ChildVue from "./views/Child.vue";
    const data = reactive({ name: 'veloma' });
    setTimeout(() => {
      data.name = 'timer';
    }, 1500);
  </script>

  // Child.vue
  <template>
    <div>{{ data.name }}</div>
  </template>

  <script lang="ts" setup>
    const props = defineProps<{
      name: string;
    }>();
    const data = reactive({ ...props });
  </script>

上面的例子在子组件中, 通过reactive将props进行了解构, Parent组件中1.5s后更新name, 这时我们会发现Child组件中的模板并不会产生更新, 那如何来解决这个问题呢?
首先有两种解决方式:

1.使用3.2.25或以上的版本直接解构defineProps, 例如这样 const { name } = defineProps<{ name: string }>()

2.或者通过computed来解构, 例如 const data = computed(() => ({ ...props }))

模板循环中加不加key的问题

关于这个问题, 在vue新文档中有提到这样一句话

只看这句话的话是没有任何问题的,但在实际的使用过程中, 举个🌰:

    // Parent.vue
    <template>
      <div>
        <ChildVue v-for="item of list" v-bind="item"></ChildVue>

        <button @click="onClick">按钮</button>
      </div>
    </template>
    <script setup lang="ts">
      import { ref } from "vue";
      import ChildVue from "./views/Child.vue";

      const list = ref([{ name: "veloma" }, { name: "timer" }, { name: "lucy" }]);

      const onClick = () => {
        console.log('点击');
        const item = { ...list.value[0] };
        item.name = "veloma1111";
 
        list.value[0] = item;
     };
    </script>
    
    // Child.vue
    <template>
      <div>{{ name }}</div>
    </template>

    <script lang="ts" setup>
      import { onMounted } from "vue";

      defineProps<{
        name: string;
      }>();

      onMounted(() => {
        console.log("mounted");
      });
    </script>

我们看上面的代码会发现功能非常的简单, 子组件接收一个name属性, 父组件循环渲染子组件, 且子组件中有一个onMounted钩子, 我们希望的是, 当点击按钮的时候触发子组件的onMounted钩子, 乍一看是没有任何问题的, 但实际是不会触发的, 看结果:

我们发现click事件确实触发了, 而数据也确实变化了, 页面也变化了, 但就是没有触发子组件的onMounted钩子, 那这是怎么回事呢?实际上在vue处理这一步的时候 重用了之前name为veloma的Child组件, 重用不会产生挂载, 也就不会触发onMounted钩子, 那要怎么解决呢?其实很简单, 只需要给Child组件一个key即可.

总结

到目前为止其实还有好多公司没有升级到vue3, 但是我相信 在不久的将来 甚至就是今年, vue3 + vite + typescript 一定会覆盖大部分的公司, 所以建议小伙伴们还是需要仔细认真的多看两遍vue的新文档, 系统的了解一下vue3的变化为以后的升级做好准备, 加油!

到此这篇关于Vue3.2.x中的小技巧及注意事项的文章就介绍到这了,更多相关Vue3.2.x小技巧内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • vue前端灵活改变后端地址两种方式

    vue前端灵活改变后端地址两种方式

    最近在学习或工作中遇到,把Vue前端项目打包后,要求可以再次修改请求后端接口的基础地址,下面这篇文章主要给大家介绍了关于vue前端灵活改变后端地址的两种方式,需要的朋友可以参考下
    2024-03-03
  • 非常实用的vue导航钩子

    非常实用的vue导航钩子

    这篇文章主要为大家分享了一个非常实用的vue导航钩子,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-03-03
  • vue3中 provide 和 inject 用法小结

    vue3中 provide 和 inject 用法小结

    父子组件传递数据时,使用的是props和emit,父传子时,使用的是 props,如果是父组件传孙组件时,就需要先传给子组件,子组件再传给孙组件,如果多个子组件或多个孙组件使用时,就需要传很多次,会很麻烦,这篇文章主要介绍了vue3中 provide 和 inject 用法,需要的朋友可以参考下
    2023-11-11
  • Vue 使用 Mint UI 实现左滑删除效果CellSwipe

    Vue 使用 Mint UI 实现左滑删除效果CellSwipe

    这篇文章主要介绍了Vue 使用 Mint UI 实现左滑删除效果CellSwipe,非常不错,具有参考借鉴价值,需要的朋友可以参考下
    2018-04-04
  • vue 动态改变静态图片以及请求网络图片的实现方法

    vue 动态改变静态图片以及请求网络图片的实现方法

    下面小编就为大家分享一篇vue 动态改变静态图片以及请求网络图片的实现方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-02-02
  • vue之el-menu-item如何更改导航菜单栏选中的背景颜色

    vue之el-menu-item如何更改导航菜单栏选中的背景颜色

    这篇文章主要介绍了vue之el-menu-item如何更改导航菜单栏选中的背景颜色问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-05-05
  • vue报错之exports is not defined问题的解决

    vue报错之exports is not defined问题的解决

    这篇文章主要介绍了vue报错之exports is not defined问题的解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-07-07
  • Vue 实时监听窗口变化 windowresize的两种方法

    Vue 实时监听窗口变化 windowresize的两种方法

    这篇文章主要介绍了Vue 实时监听窗口变化 windowresize的两种方法,非常不错,具有一定的参考借鉴价值,需要的朋友可以参考下
    2018-11-11
  • vue3新增Teleport的问题

    vue3新增Teleport的问题

    这篇文章主要介绍了vue3新增Teleport的问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-08-08
  • 详解mpvue中小程序自定义导航组件开发指南

    详解mpvue中小程序自定义导航组件开发指南

    这篇笔记主要记录一下基于mpvue的小程序中实现自定义导航的思路及应用。小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2019-02-02

最新评论