【一】Vue3组件化知识及项目创建

279 阅读3分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第11天,点击查看活动详情

一、Vue3组件化知识

组件命名

官方建议我们使用大拖缝命名法注册组件,因为:

  1. 驼峰命名是合法的 JS标识符,导入、注册组件会更简单,IDE会自动完成。
  2. <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 中,那些没有目前在组件 propsemits 中声明的特性或事件监听器称为透传特性,以前叫非属性特性。例如 classstyleid 特性。当组件只有单根时,透传特性自动被添加到根元素上作为其特性。例如:

<!-- 组件使用 -->
<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

选择 vuets 即可

  • 添加 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.jstsconfig.json

  • package.json 中给 script 添加一条指令
"lint": "eslint . --ext .js,.ts,.tsx,.vue"

之后在命令行跑测试:npm run lint,就可看到 eslint 的报错信息了

2.png

  • 修改 .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