vue3 学习
ref 和 reactive
- 我的理解是 原则上是区分基本类型(ref)和引用类型(reactive)的。功能是一样的,其实是两种风格的代码
1 | // 风格1 |
- ref 代码片段 注意 ref 必有 value
1 | <template> |
- reactive 注意返回对象 形式(toRefs)
1 | <template> |
生命周期对应
vue2 | vue3 |
---|---|
created | setup |
beforeCreate | setup |
beforeMount | onBeforeMount |
mounted | onMounted |
beforeUpdate | onBeforeUpdate |
updated | onUpdated |
beforeDestroy | onBeforeUnmount |
destroyed | onUnmounted |
activated | onActivated |
onRenderTriggered 新增调试生命周期
1 | import { onMounted, onUpdated, onRenderTriggered } from "vue"; |
watch
1 | import { computed, reactive, toRefs, ref, watch } from "vue"; |
computed
- 如果一个对象中包含响应式的属性,需要用 computed 包裹这个对象返回
- 注意 computed 包裹对象后 需要.value
1 | const currentPage = ref(params.currentPage); |
hooks 模块化
- 场景:需要抽离一个鼠标位置的功能
- 在 src/hooks/useMousePosition.ts
1 | import { ref, onMounted, onUnmounted } from 'vue' |
- 在任意组件中使用
1 | <template> |
hooks 模块化 2
- 场景: 接口请求 loading 效果
- 在 src/hooks/useURLLoader.ts
1 | import axios from 'axios' |
- 在任意组件中使用
1 | <template> |
一个弹窗组件 teleport(瞬间移动)
- 在 index.html 增加一个空 DIV#modal 作为弹窗组件的父级,和#app 并列(不会被业务样式干扰)
1 | <body> |
- modal 组件 (teleport 用法,emits 需要作为一个 option 否则报警告)
1 | <template> |
- 正常在业务组件中使用
1 | <template> |
异步组件 supense
- 场景:组件内容需要异步加载
AsyncShow.vue
1 | <template> |
- 使用
1 | <template #default> |
createApp
- 不同于 vue2 属性和方法都在 vue 上挂在,容易污染全局,vue3 通过 createApp 创建 app 实例挂载
1 | import { createApp } from 'vue' |
VUE3 使用 es6 import 引入一些行为 可以更好的 treeShaking
1 | import {nextTick,observable} from 'vue' |
- 不同于 vue2 使用 Vue.nextTick Vue.observable 这样可以 treeShaking
hooks & 点击其他地方 让下拉菜单关闭
- hooks/useClickOutside.js
1 | //点击任意位置 看是否在指定元素内 (用做点任意位置收起下拉菜单) |
- 使用
1 | <template> |
组件 v-model
v-model 语法语法糖拆解
- 组件内部 input 去掉 v-model 改成 :value = “inputRef.val”
- 组件内部 input 增加 @input 方法 其实就是不用 v-model 语法糖了
- 组件内部 props 上增加 modelValue
- 定义@input 方法 并在方法内部 emit(‘update:modelValue’)
- 父组件中使用
<child v-model="emailVal"></child>
子组件
1 | <input :value="inputRef.val" @input="updateValue"> |
父组件 直接使用
1 | <ValidateInput placeholder="shit" v-model="emailVal" :rules="emailRules"></ValidateInput> |
组件 v-model 实践
父组件 可以传递多个 v-model
1 | <div id="app"> |
路由
- 路由配置 main.ts
1 | import { createRouter, createWebHistory } from 'vue-router' |
- 使用 useRoute 获取路由信息
1 | import { useRoute } from "vue-router"; |
- 使用 userRouter 来设置路由的行为
1 | import { useRouter } from "vue-router"; |
vuex
- main.js
1 | import store from './store' |
- store.js
1 | import { createStore } from 'vuex' |
- 组件内使用
1 | import { useStore } from "vuex"; |
commit
1 | setup() { |
- getters
getters 的作用是可以将 state 的值做一些处理
否则在多地方用 都要自己写一遍 computed 处理
1 | getters: { |
1 | const bigger = computed(() => store.getters.biggerColumnsLen); |
- getters 也可以是一个函数 传入参数
1 | getters: { |
使用
1 | setup() { |
classList 设置在 DOM 上添加和删除一个类
比如 $el对象 (一般是VUE实例关联的DOM对象 本项目中components/base/loading/directive.js中用到)
或者 dom 上的 ref (this.$refs.xxx)1
2this.$refs.recommend.classList.add('test'),
this.$el.classList.remove('recommend')以上的$el 指当前 vue 组件上的根节点
本项目中根据指令封装
1
2
3
4
5
6
7
8
9
10export function addClass(el, className) {
if (!el.classList.contains(className)) {
el.classList.add(className)
}
}
export function removeClass(el, className) {
el.classList.remove(className)
}loading 自定义指令 (含动态参数)
使用
1 | <div class="recommend" v-loading:[loadingText]="loading"></div> |
- main.js 导入
1 | import loadingDirective from '@/components/base/loading/directive' |
- 具体代码见 vue3-music base/loading
过渡动画
- 点击按钮进入子路由过渡,屏幕右侧抽屉效果
css
1 | .slide-enter-active,.slide-leave-active { |
- 路由部分
name=”slide” slide 对应样式 slide-enter-active….
appear 代表进入就有动画
1 | <router-view v-slot="{Component}"> |