Files
KintoneAppBuilder/frontend/VUE3.0-coding-rule.md

242 lines
9.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

以下是一份 Vue 3 和 TypeScript 的编程规范:
**1. 组件定义**
- 推荐使用 `defineComponent` 来定义组件,以获取 TypeScript 的类型支持。
```typescript
import { defineComponent } from 'vue'
export default defineComponent({
// 组件选项
})
```
**2. 数据定义**
- 使用 `reactive` 定义响应式对象。
- 使用 `ref` 定义响应式单值。
- 使用 `computed` 定义计算属性。
```typescript
import { reactive, ref, computed } from 'vue'
const state = reactive({
count: 0,
message: 'Hello Vue 3'
})
const count = ref(0)
const doubledCount = computed(() => state.count * 2)
```
**3. 生命周期钩子**
- 使用 `onMounted``onUpdated` 等生命周期钩子,而不是 `beforeCreate``created``beforeMount``mounted``beforeUpdate``updated``beforeUnmount``unmounted`
```typescript
import { onMounted } from 'vue'
onMounted(() => {
console.log('Component is mounted.')
})
```
**4. 组件通信**
- 使用 `props``emit` 实现父子组件通信。
- 使用 `provide``inject` 实现祖先和后代组件通信。
- 不再推荐使用 `event bus` 进行任意组件间的通信,可以使用 Vuex 或者全局 `provide`/`inject` 替代。
```typescript
// 父组件
<ChildComponent @my-event="handleEvent" />
// 子组件
this.$emit('my-event', eventData)
```
**5. 异步处理**
- 使用 `async/await` 进行异步处理。
- 使用 `Suspense``async setup()` 处理异步依赖。
```typescript
import { ref, onMounted } from 'vue'
import axios from 'axios'
onMounted(async () => {
const response = await axios.get('https://api.example.com/data')
data.value = response.data
})
```
**6. Vue Router 和 Vuex**
- 使用 Vue Router 4 和 Vuex 4它们是为 Vue 3 重新设计的。
- 使用 `useRouter``useRoute` 钩子函数在组件中使用 router。
- 使用 `useStore` 钩子函数在组件中使用 Vuex store。
```typescript
import { useStore } from 'vuex'
import { useRouter } from 'vue-router'
const store = useStore()
const router = useRouter()
```
**7. 组件模板**
- 使用 `v-model` 代替 `.sync` 修饰符进行双向绑定。
- 使用 `v-for``:key` 渲染列表。
- 使用 `v-if``v-else``v-else-if` 进行条件渲染。
- 使用 `v-on` 或者 `@` 监听事件。
- 使用 `v-bind` 或者 `:` 绑定属性。
```html
<template>
<div v-if="condition">If block</div>
<div v-else>Else block</div>
<ul>
<li v-for="(item, index) in list" :key="index">{{ item }}</li>
</ul>
<button @click="handleClick">Click me</button>
</template>
```
8. **使用类型注解和接口**
在 TypeScript 中,尽可能使用类型注解和接口来提供更完善的类型信息和类型检查。这将有助于发现和预防错误。
```typescript
interface User {
name: string;
age: number;
}
const user: User = {
name: 'John',
age: 30
}
```
9. **模块化和组件化**
尽可能将功能和逻辑模块化和组件化,使得代码更易于理解和维护。特别是使用 Composition API 时,可以将公共的逻辑封装成 composable 函数。
下面是一个使用 `Suspense` 和 `axios` 的示例,这个示例将会从一个 JSON Placeholder API 获取数据:
首先,我们创建一个 composable 函数,用于获取数据:
```typescript
import { ref } from 'vue'
import axios from 'axios'
export function useAsyncData(url: string) {
const data = ref(null)
const error = ref(null)
const fetchData = async () => {
try {
const response = await axios.get(url)
data.value = response.data
} catch (e) {
error.value = e
}
}
return { data, error, fetchData }
}
```
然后,我们创建一个 Vue 组件来使用这个函数:
```js
<template>
<Suspense>
<template #default>
<div v-if="error">{{ error.message }}</div>
<div v-else>{{ data }}</div>
</template>
<template #fallback>
<div>Loading...</div>
</template>
</Suspense>
</template>
<script lang="ts">
import { defineComponent, onMounted } from 'vue'
import { useAsyncData } from './composables/useAsyncData'
export default defineComponent({
setup() {
const { data, error, fetchData } = useAsyncData('https://jsonplaceholder.typicode.com/posts/1')
onMounted(fetchData)
return { data, error }
},
})
</script>
<style scoped>
/* 在这里添加 CSS 样式 */
</style>
```
在这个示例中,我们在 `useAsyncData` 函数中获取数据。当 `onMounted` 钩子函数被调用时(也就是当组件挂载完成后),我们开始获取数据。这个过程是异步的,因此我们在 `Suspense` 组件的 `#fallback` 插槽中显示一个 "Loading..." 的提示。一旦数据加载完成,`Suspense` 组件的 `#default` 插槽就会被渲染,并显示获取到的数据。
10. **良好的代码风格**
遵循一致的代码风格和代码质量规则,例如使用 ESLint 和 Prettier 来检查和格式化代码。
11. **单元测试和端到端测试**
对关键的组件和函数编写单元测试,对用户的主要操作路径编写端到端测试,确保功能的正确性。
12. **注释和文档**
对复杂的逻辑和函数编写注释,提供必要的项目文档,帮助其他开发者理解和使用你的代码。
13. **以下是 Vue 2 中被废弃或改变的部分API以及在 Vue 3 中的替代方案:**
| Vue 2.x | Vue 3.0 | 说明 |
| --- | --- | --- |
| `Vue.set` / `this.$set` | 响应式数据现在是默认的,无需使用这些方法 | Vue 3 的响应式系统是从头开始构建的,所有的对象和数组都是响应式的 |
| `Vue.delete` / `this.$delete` | 无需使用这些方法 | 在 Vue 3 中,你只需要使用 `delete` 操作符即可 |
| `filters` | 无对应项 | Vue 3 不再支持过滤器,建议使用计算属性或方法替代 |
| `Vue.observable` | `reactive` | 用 `reactive` 替代 `Vue.observable`,实现数据的响应式 |
| `Vue.prototype` | `app.config.globalProperties` | 在 Vue 3 中,全局 API 已经改变,`Vue.prototype` 被 `app.config.globalProperties` 替代 |
| `Vue.component`, `Vue.directive`, `Vue.mixin`, `Vue.use` | `app.component`, `app.directive`, `app.mixin`, `app.use` | 全局注册的 API 改变,如 `Vue.component` 变为 `app.component` |
| `beforeDestroy` 和 `destroyed` 生命周期钩子 | `beforeUnmount` 和 `unmounted` | 生命周期钩子名字变化,`beforeDestroy` 和 `destroyed` 分别改为 `beforeUnmount` 和 `unmounted` |
| `$on`, `$off`, `$once` | 无对应项 | Event Bus方法被移除需要用户自行实现或者使用第三方库 |
| `v-model` 在自定义组件上使用 | 需要明确的 `modelValue` 和 `update:modelValue` | Vue 3 对 `v-model` 的改动使其在自定义组件上更具灵活性 |
| `functional` 选项 | 无对应项 | Vue 3 不再支持函数式组件的写法,而是推荐使用 `render` 函数或 `setup` 函数 |
| 异步组件的 `functional` 写法 | `defineAsyncComponent` | 异步组件的创建方式更改,通过 `defineAsyncComponent` 方法创建 |
| `destroyed` 和 `beforeDestroy` 钩子函数 | `unmounted` 和 `beforeUnmount` | 生命周期钩子的名称已改为更直观的名称,以更好地表示其在组件实例生命周期中的角色 |
| `Vue.extend` | `defineComponent` | Vue 3 使用 `defineComponent` 方法定义组件,有更好的类型推断 |
注意Vue 3 对于 Options API 和 Composition API 提供了完全的支持,你可以在一个组件中混合使用这两种 API。不过为了代码的一致性和可读性建议在一个项目中选择一种 API 并坚持使用。
- **以下是 Vue 3.0 中的 Composition API 函数的基本说明,以及与 Options API 的对比**
| Composition API | 说明 | 对应的 Options API |
| --------------- | ---- | ------------------ |
| `setup` | `setup` 是一个新引入的组件选项,用于使用 Composition API。它是组件内部使用 Composition API 的入口。| 无 |
| `ref` | `ref` 函数用于创建一个响应式的数据。它接收一个参数,返回一个响应式的 Ref 对象。| `data` |
| `reactive` | `reactive` 函数用于创建一个响应式的对象。它接收一个普通对象,返回一个响应式的对象。| `data` |
| `computed` | `computed` 函数用于创建一个计算属性。它接收一个 getter 函数或者一个具有 getter 和 setter 的对象,返回一个响应式的 Ref 对象。| `computed` |
| `watch` | `watch` 函数用于响应式地跟踪和触发副作用。它接收一个响应式的源和一个执行副作用的回调函数。| `watch` |
| `watchEffect` | `watchEffect` 函数用于立即执行传入的一个函数,并响应式地追踪其依赖,并在其依赖变更时重新运行该函数。 | 无 |
| `onMounted` | `onMounted` 函数在组件被挂载时调用。它接收一个在组件挂载后执行的回调函数。 | `mounted` |
| `onUnmounted` | `onUnmounted` 函数在组件被卸载时调用。它接收一个在组件卸载后执行的回调函数。 | `beforeDestroy`/`unmounted` |
| `onUpdated` | `onUpdated` 在组件更新后调用。它接收一个在组件更新后执行的回调函数。| `updated` |
| `provide` | `provide` 函数用于在组件上定义一个可以被后代组件注入的值。它接收一个提供的键和值。 | 有,与 `provide/inject` 相似但是属性而不是函数 |
| `inject` | `inject` 函数用于在组件中注入一个由祖先组件提供的值。它接收一个注入的键。 | 有,但与 `provide/inject` 相似但是属性而不是函数 |
值得注意的是,虽然一些 Composition API 函数与 Options API 的某些选项有相似之处,但它们的工作方式和使用方式可能有所不同。在实际使用中,你需要根据具体的使用场景和需求选择合适的 API。