携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第11天,点击查看活动详情
一、Vue3组件化知识
组件命名
官方建议我们使用大拖缝命名法注册组件,因为:
- 驼峰命名是合法的
JS标识符,导入、注册组件会更简单,IDE会自动完成。 <Pascalcase />使Vue组件比原生 HTML 元素更醒目
属性定义
使用更细节的方式定义属性:
<script setup>
// 不推荐
// const props = defineProps(["foo"])
// 推荐
const props = defineProps({
foo: { type: String, default: "" }
})
console.log(props.foo)
</script>
事件定义
自定义事件的名称会被自动做转换,我们通常用驼峰做事件名,但监听时需要转换为烤串的方式
例如:
<!-- MyComponent -->
<button @click="$emit("someEvent")">click me</button>
<!-- 使用 -->
<MyComponent @some-event="callback" />
在 setup 中定义
<script setup lang="ts">
const emit = defineEmits(["someEvent"])
emit("someEvent")
</script>
透传特性
在 vue3 中,那些没有目前在组件 props 和 emits 中声明的特性或事件监听器称为透传特性,以前叫非属性特性。例如 class,style 和 id 特性。当组件只有单根时,透传特性自动被添加到根元素上作为其特性。例如:
<!-- 组件使用 -->
<MyButton class="large" />
<!-- 组件内部会自动继承class -->
<button class="large">click me</button>
如果不想自动继承特性,可以使用 inheritAttrs: false 禁止
<script>
export default {
inheritAttrs: false
}
</script>
<script setup>
// setup内容
</script>
访问透传特性
<script setup>
import { useAttrs } from "vue"
const attrs = useAttrs()
</script>
插槽
如果要传递模板内容给子组件,可以使用插槽。
vue3中的插槽移除了 scopeSlots,只需要访问 slots 对象,且包括 default 插槽都是函数形式。
<script setup>
import { useSlots } from "vue"
const slots = useSlots()
const defaultContent = slots.default()
</script>
提供/注入(provide/inject)
隔代传参,使用 provide/inject 这组 API
这组API在开发原生组件时非常有用,因为很多时候我们不希望一层层去传递参数
<script setup>
import { provide } from "vue"
// 祖代提供数据
provide(/* key */ "message", /* value */ "hello!")
</script>
<script setup>
import { inject } from "vue"
// 后代接收数据
const msg = inject("messgae", "defaultValue")
</script>
Composables:hooks
利用 Composition API 封装的课重用状态逻辑称为 composables。
约定 composables 函数命名时加上 use 前缀,例如:
// mouse.js
import { ref, onMounted, onUnmounted } from "vue"
export function useMouse() {
const x = ref(0)
const y = ref(0)
function update(event) {
x.value = event.pageX
y.value = event.pageY
}
onMounted(() => window.addEventListener("mousemove", update))
onUnmounted(() => window.removeEventListener("mousemove", update))
return { x, y }
}
建议:进入 ref,返回 ref
- 总是传入
ref对象,总是使用unref解包 - 总是返回
ref对象
import { unref } from "vue"
function useXXX(refVal) { // 传入ref对象
const value = unref(refVal) // 使用unref解包
}
const { x, y } = useMouse() // 总是返回 ref 对象
组件通信
- 父子通信:props、emit
const props = defineProps({
model: { type: Object, required: true }
})
console.log(props.model)
const emit = defineEmits<{
(e: "update:model-value", value: string): void;
(e: "validate"): void;
}>();
const emit1 = defineEmits(["update:model-value", "validate"]) // 和上面类似
emit("update:model-value", input.value)
emit 选项
用于标注自定义事件及其校验等。
createApp({}).component("comp", {
template: "...",
// emits标明对外事件
emits: ["buy", "..."],
// 还能对事件进行校验
emits: {
"update:modelValue": null, // 不做校验
buy(p) { // 校验buy事件
if(p === "nothing") {
console.warn("参数非法")
return false
} else {
return true
}
}
}
})
二、项目搭建
1、创建项目
pnpm create vite
选择 vue、ts 即可
- 添加
jsx依赖
pnpm add @vitejs/plugin-vue-jsx -D
- 修改配置
// vite.config.ts
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import vueJsx from "@vitejs/plugin-vue-jsx" // 添加插件导入
export default defineConfig({
plugins: [vue(), vueJsx()]
})
2、代码规范
- 初始化
eslint
npx eslint --init
选择:problems => esm => vue => use TS => browser => JavaScript
此时,项目中会多出两个文件:.eslintrc.js 和 tsconfig.json
- 在
package.json中给script添加一条指令
"lint": "eslint . --ext .js,.ts,.tsx,.vue"
之后在命令行跑测试:npm run lint,就可看到 eslint 的报错信息了
- 修改
.eslintrc.js
module.exports = {
"extends": [
"plugin:vue/vue3-recommended", // 只需要这个
],
}
另一种选择
上面的 eslint 是正常流程的规范,我这边选择自己的 eslint 规范:@hayeslv/eslint-config
- 安装
pnpm add -D @hayeslv/eslint-config
- 修改
package.json
{
...
"eslintConfig": {
"extends": [
"@hayeslv"
],
"rules": {}
}
}
- 最后,如果执行过上面的
eslint流程的话,记得删除.eslintrc.js文件
安装 lint-staged 以及 husky的默认配置
npx mrm@2 lint-staged