本文学习过程中遇到的一些问题和相应的解决方案,不一定是最佳解决方案。如有更好的解决方案,欢迎评论区留言讨论。
学习文档
原生问题
- setTimeout 类型问题:
请加入 window
开头表示是 web 的,不然编辑器要求使用 NodeJS.Timeout
类型,但是编译又编不过。
let timer: number = window.setTimeout(() => {
...
}, 17)
复制代码
setInterval
等同理。
- Map
优先使用 Map 对象来实现需求,而不是普通对象,不然在类型判断上比较难搞。
const modeMaps = new Map<string, string>([
['clickable', 'RightOutlined'],
['closable', 'CloseOutlined']
])
复制代码
而不是:
const modeMap = {
'clickable': 'RightOutlined',
'closable': 'CloseOutlined',
}
复制代码
Eslint 配置
- 使用以下标准,不然有未知问题。
extends: [
'plugin:vue/vue3-essential',
'eslint:recommended',
'@vue/typescript/recommended',
'@vue/prettier',
'@vue/prettier/@typescript-eslint'
]
复制代码
- 还有关闭要优先定义的规则,不然有些相互引用的业务没法满足这规则。
rules: {
'@typescript-eslint/no-use-before-define': 'off',
'@typescript-eslint/no-empty-function': 'off',
'@typescript-eslint/camelcase': 'off',
'@typescript-eslint/no-explicit-any': 'off',
}
复制代码
alias 别名
安装 require 相关声明
npm i -D @types/node
复制代码
vue-cil 处理方式
const { resolve } = require('path')
module.exports = {
chainWebpack: config => {
// alias
config.resolve.alias.set('@', resolve('path/to/xxx'))
}
}
复制代码
vite 处理方式
vite.config.ts
const { resolve } = require('path')
export default defineConfig({
resolve: {
alias: [{ find: '@', replacement: resolve('path/to/xxx') }]
}
})
复制代码
Vue reactive
Proxy
实现响应式其实是将一个 raw 对象包装了一层,产生了一个新的对象,可能会存在原始对象占用内存并且无法释放的问题,所以在将一个对象声明响应式时,尽量不要用任何的变量去引用原始对象,而是直接将该对象放在 reactive
中。
不太推荐的做法:
import {reactive} from 'vue'
export default {
setup() {
let obj = { name: '零一', age: 23 } // 原始对象
const state = reactive(obj) // 将obj包装成响应式
return {state}
}
}
复制代码
推荐的做法:
import {reactive} from 'vue'
export default {
setup() {
// 不再先声明原始对象
const state = reactive({ name: '零一', age: 23 })
return {state}
}
}
复制代码
Vue Props
- 函数类型
官方有介绍。
- 枚举类型
mode: {
type: String as PropType<'clickable' | 'closable'>,
default: 'default'
},
复制代码
- validator 或者 default 是函数的情况下,使用
=>
,不然会导致 setup 的 props 参数 Typescript 异常
shape: {
validator: value => value.length >= 2,
default: () => []
}
复制代码
PS:如果是引用的函数,被引用的函数也要确保是 =>
形式的
Vue Watch
- 监控 props.xxx ,推荐使用 getter 函数的形式
watch(() => props.xxx, () => {
...
})
复制代码
如果 props.xxx 是对象或者数组
watch(() => props.xxx, () => {
...
}, {
deep: true
})
复制代码
Vue ref
- 引用 DOM
<div ref="root"></div>
复制代码
setup() {
const root = ref(null)
...
onMounted(() => {
console.log(root.value) // HTMLElement
})
return {
root
}
}
复制代码
在 Typescript 中,应该这么写:
setup() {
const root = ref<HTMLElement>()
...
onMounted(() => {
console.log(root.value as HTMLElement) // HTMLElement
})
return {
root
}
}
复制代码
- 引用组件
import FooComponent from 'path/to/FooComponent.vue'
setup() {
const foo = shallowRef<ComponentPublicInstance<typeof FooComponent>>()
...
onMounted(() => {
console.log(foo.value as ComponentPublicInstance) // ComponentPublicInstance
})
return {
foo
}
}
复制代码
Svg 图标
vue-cli 构建的用 vue-svg-loader
- 安装依赖
npm i -D vue-svg-loader@beta vue-loader
复制代码
注:是跟 vue 同步的 beta 版本
- 在 vue.config.js 中配置
chainWebpack: config => {
// svg
const svgRule = config.module.rule('svg')
svgRule.uses.clear()
svgRule
.use('vue-loader-v16')
.loader('vue-loader-v16') // or `vue-loader-v16` if you are using a preview support of Vue 3 in Vue CLI
.end()
.use('vue-svg-loader')
.loader('vue-svg-loader')
}
复制代码
使用 vite 构建的用 vite-svg-loader
- 安装
npm install vite-svg-loader --save-dev
复制代码
- 应用
vite.config.ts
import svgLoader from 'vite-svg-loader'
export default {
plugins: [vue(), svgLoader()]
}
复制代码
tsconfig.json
{
"compilerOptions": {
"types": ["vite-svg-loader", "vite/client"]
}
}
复制代码
使用 markRaw 标记返回对象本身
import { markRaw, defineComponent } from 'vue'
import TaobaoSvg from './svgs/taobao.svg'
export default defineComponent({
setup() {
return {
TaobaoSvg: markRaw(TaobaoSvg)
}
}
})
复制代码
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END