vue3.0
vue3.0
开发工具
- (新的友好的支持 vue3 的 vscode 开发插件) volar
- (官方脚手架工具 create-vue)[https://github.com/vuejs/create-vue]
- (Vitesse)[https://github.com/antfu/vitesse]
- (vue3-eslint-stylelint-demo) [https://github.com/sethidden/vue3-eslint-stylelint-demo](Volar + ESLint + stylelint + husky)
- (volar-starter)[https://github.com/johnsoncodehk/volar-starter] (For bug report and experiment features testing)
生命周期
destroyed 生命周期选项被重命名为 unmounted
beforeDestroy 生命周期选项被重命名为 beforeUnmount
Composition API 简单使用
teleport 组件
有时组件模板的一部分逻辑上属于该组件,而从技术角度来看,最好将模板的这一部分移动到 DOM 中 Vue app 之外的其他位置。
Teleport 提供了一种干净的方法,允许我们控制在 DOM 中哪个父节点下渲染了 HTML,而不必求助于全局状态或将其拆分为两个组件
1 | <teleport to="#modals"> |
stylelint
StyleLint 是『一个强大的、现代化的 CSS 检测工具』, 与 ESLint 类似, 是通过定义一系列的编码风格规则帮助我们避免在样式表中出现错误.
(StyleLint 使用指南)[https://www.cnblogs.com/jiaoshou/p/11284204.html]
setup 的形参
1 | <script setup></script> |
采用 script setup 语法糖的话这种方式就不可行了,原因是它会自动以文件名为主,不需要在写 name 属性
需要设置 name 直接在 script setup 同级中再添加一个 script 即可。
1 | <script> |
如果同时使用了 typescript 的话,可以配合插件直接在 script 标签中设置 name,具体方式如下:
安装插件:vite-plugin-vue-setup-extend
1 | <script lang="ts" setup name="xxx"></script> |
reactive()
和 ref()
的比对
- ref() 单独地为某个数据提供响应式能力
想要保持对象内容的响应式能力,在 return 的时候必须把整个 reactive() 对象返回出去,同时在引用的时候也必须对整个对象进行引用而无法解构,否则这个对象内容的响应式能力将会丢失。
- reactive() 给一整个对象赋予响应式能力
在具体的业务中,如果无法使用解构取出 reactive() 对象的值,每次都需要通过 . 操作符访问它里面的属性会是非常麻烦的,所以官方提供了 toRefs() 函数来为我们填好这个坑。只要使用 toRefs() 把 reactive() 对象包装一下,就能够通过解构单独使用它里面的内容了,而此时的内容也依然维持着响应式的特性。
1 | setup() { |
isRef,unRef,toRef 和 toRefs
1 | let foo: unknown; |
ref、reactive、shallowRef、 shallowReactive、toRaw、unref、toRef、toRefs、customRef
shallowRef & shallowReactive 只对对象的第一层做监听变化
customRef 创建一个自定义的 ref,并对其依赖项跟踪和更新触发进行显式控制。它需要一个工厂函数,该函数接收 track 和 trigger 函数作为参数,并且应该返回一个带有 get 和 set 的对象
1 | function useDebouncedRef(value, delay = 200) { |
定义 prop emit
- defineProps
1 | import { defineProps } from "vue"; |
- defineEmits
1 | import { defineEmits } from "vue"; |
子组件
1 | <template> |
父组件
1 | <template> |
- defineExpose
script setup 默认是不对外界暴露组件实例的,所以在其他组件中通过诸如$refs和$parent 都默认无法获取当前组件实例,但是通过 defineExpose 暴露的可以获取。
显示暴露的数据,才可以在父组件拿到
1 | <script setup lang="ts"> |
使用 slots 和 attrs
- 通过 useSlots 和 useAttrs 来定义,达到类似$slots和$attrs 的效果
1 | // 导入 useAttrs 组件 |
使用 provide 给子孙组件传值和 inject 接收父组件的值
父组件
1 | <script setup lang="ts"> |
孙子组件
1 | <script setup lang="ts"> |
watch 和 watchEffect
- watch ()
第一个参数为观察 ref 物件,第二个参数为一个 callBack ,当状态更新,就会针对其来执行 callback。
- watchEffect()
不用指定要监听的目标,只要在 callback 函式中对应响应式资料更新后就会依照对应资料来执行了,而与 watch 不同的是,watchEffect () 在初始 setup () 的时候,就会先执行一次了。
第一个参数还可以是队列,如果是 reative 中的一个 key-value,用有回传值的 getter 函式,即()=>state.key,深度监听在第三个参数{deep: true}
v-model 的参数分析
v-model 其实是做双向绑定,实际上是语法糖
vue2.x.x 的语法
1 |
|
vue3.x.x 的语法
- 2.x 的 v-model 只能有一个,3.x 灵活为支持多个
1 | <ChildComponent v-model:title="pageTitle" v-model:content="pageContent" /> |
- 除了像 .trim 这样的 2.x 硬编码的 v-model 修饰符外,现在 3.x 还支持自定义修饰符
1 | <ChildComponent v-model.capitalize="pageTitle" /> |
1 | <!-- 1 --> |
VueUse
为 Vue 2 和 3 服务的一套 Vue Composition API 的常用工具集,是目前世界上 Star 最高的同类型库之一。它的初衷就是将一切原本并不支持响应式的 JS API 变得支持响应式,省去程序员自己写相关代码。
(官网)[https://vueuse.org/guide/index.html]
实现细节
vue.install
资料
ts 相关支持
实现注入到 vue 实例上的声明定义
1 | class PrototypeUtils { |
vuex
Pinia API
- 没有 mutations,用$patch 代替
- 更好 typescript 支持
- 没有命名空间模块
- 定义
1 | // store/user.js中定义具体的store |
- 使用
1 | import UserStore from "@/store"; |
style v-bind
css 变量的 hack 结合 vue
1 | <template> |
拓展(原生 css 变量)
- 变量声明
1 | body { |
为什么选择两根连词线(–)表示变量?因为$foo 被 Sass 用掉了,@foo 被 Less 用掉了。为了不产生冲突,官方的 CSS 变量就改用两根连词线了。 2. 变量应用 2. var 变量
1 | a { |
同一个 CSS 变量,可以在多个选择器内声明。读取的时候,优先级最高的声明生效
JavaScript 操作 CSS 变量
1 | // 设置变量 |
常用 tips
- vue3 的路由懒加载
1 | // 3.x |
- vite&webpack 动态加载
1 | // vite 动态添加模块 |
- vite 中使用批量导入 import.meta.glob 和 import.meta.globEager 区别
- import.meta.glob 为过动态导入,构建时,会分离为独立的 chunk
- import.meta.globEager 为直接引入
- (glob-import)[https://cn.vitejs.dev/guide/features.html#glob-import]
- (pattern-syntax)[https://github.com/mrmlnc/fast-glob#pattern-syntax]
import.meta.globEager 已弃用,用 import.meta.glob(‘_‘, { eager: true }) 来代替。
- vite 预构建缓存问题
Vite 有个预构建阶段,用于将 commonjs/UMD 模块转为 ESM,和合并多个模块。就是把一些模块处理后放在 node_modules/.vite/deps 目录下,项目启动时直接引用这个目录下的内容。
值得注意的是,这一阶段是有缓存的,且存在两处缓存,一处是.vite/deps 下的缓存,一处是浏览器的缓存。如果发现修改了插件,但是观察不到效果,可以尝试 npx vite –fore,以及禁用浏览器缓存。
- vue 和 typescript
ts-loader:让 webpack 能够识别 ts 文件
由于 TypeScript 默认并不支持 *.vue 后缀的文件,所以在 vue 项目中引入的时候需要创建一个 vue-shim.d.ts 文件,放在根目录下
1 | declare module "*.vue" { |
v-slot:xxx 的语法糖#xxx
jsx/tsx 中如何使用插槽
jsx 插槽webpack 和 Vite 环境变量区别
webpack,vite 配置.env。test,.env.development 文件和.env.production 文件
script 中可以通过添加–mode development 指定环境变量
webpack 可以在项目中通过 process.env.[name]来访问我们定义的变量
vite 则是通过 import.meta.env.[name]来访问
Vite 为了防止意外地将一些环境变量泄漏到客户端,只有以 VITE_ 为前缀的变量才会暴露给经过 vite 处理的代码
vue 的 webpack 当我们配置环境变量时候,除了 process.env 已有的 baseUrl 和 NODE_ENV 可以更改值,对于我们想要自定义添加的环境变量必须使用 VUE_APP 开头。
1 | npm run build:test # webpack |
1 | import { defineConfig, loadEnv } from "vite"; |