diff --git a/frontend/README.md b/frontend/README.md index 6d6096c..4dea4d1 100644 --- a/frontend/README.md +++ b/frontend/README.md @@ -47,3 +47,7 @@ quasar build ### Customize the configuration See [Configuring quasar.config.js](https://v2.quasar.dev/quasar-cli-vite/quasar-config-js). + +## VUE3.0编程规范 +1. [VUE3.0编程概要](./VUE3.0概要.md) +2. [VUE3.0编程规范](./VUE3.0-coding-rule.md) diff --git a/frontend/VUE3.0-coding-rule.md b/frontend/VUE3.0-coding-rule.md new file mode 100644 index 0000000..2bf920a --- /dev/null +++ b/frontend/VUE3.0-coding-rule.md @@ -0,0 +1,241 @@ +以下是一份 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 +// 父组件 + + +// 子组件 +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 + +``` + +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 + + + + + + ``` + + 在这个示例中,我们在 `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。 diff --git a/frontend/vue3.0概要.md b/frontend/vue3.0概要.md new file mode 100644 index 0000000..972d895 --- /dev/null +++ b/frontend/vue3.0概要.md @@ -0,0 +1,1075 @@ +Vue 3.0 引入了很多新的 API 和功能,同时也保留了 Vue 2.x 的很多特性。以下是一个关于 Vue 3.0 常用功能的编程标准指南纲要: +1. **项目和组件结构** + - 项目目录和文件命名 + - 单文件组件的结构:template, script, style + +2. **组件数据** + - 定义和使用 props + - 定义和使用组件内部数据:`ref` 和 `reactive` + - 使用 `computed` 属性 + - 使用 `watch` 和 `watchEffect` 监听数据变化 + +3. **模板语法** + - 插值:文本,HTML + - 指令:v-model, v-if/v-else-if/v-else, v-show, v-for, v-bind, v-on + - 过滤器和全局混入(虽然 Vue 3.0 推荐尽量避免使用,但在一些场景仍有用) + +4. **组件通信** + - 使用 props 和自定义事件实现父子组件通信 + - 使用 `provide`/`inject` 实现祖先和后代组件通信 + - 使用 event bus 进行任意组件间的通信(Vue 3.0 不再内置,但可以自行实现) + - 使用 Vue 3.0 的新功能 `teleport` 进行组件内容的传输 + +5. **Composition API** + - 使用 `setup` 函数 + - 使用 `ref`, `reactive`, `computed`, `watch`, `watchEffect` + - 创建和使用 composable 函数 + +6. **路由和状态管理** + - 使用 Vue Router:定义和使用路由,导航守卫,路由元信息 + - 使用 Vuex:状态定义,Getter,Mutation,Action,模块化状态 + +7. **与外部交互** + - 使用 `axios` 或者 `fetch` 进行 HTTP 请求 + - 使用 Vue 3.0 的新功能 `Suspense` 进行异步依赖处理 + +8. **测试和部署** + - 单元测试:使用 Jest 编写和运行测试 + - E2E 测试:使用 Cypress 编写和运行测试 + - 部署:编译,打包,发布 + +1. **项目和组件结构** + - 项目目录和文件命名 + Vue 项目和组件的结构可以因项目需求和开发团队偏好而有所不同,但这里提供一种推荐的目录结构: + + ``` + /my-app + ├── /node_modules + ├── /public + │ ├── index.html + │ └── favicon.ico + ├── /src + │ ├── /assets // 静态资源如图片、样式等 + │ ├── /components // Vue 组件 + │ ├── /router // Vue Router 配置 + │ ├── /store // Vuex 状态管理配置 + │ ├── /views // 页面级 Vue 组件 + │ ├── App.vue // 根组件 + │ ├── main.ts // 应用入口文件 + │ ├── shims-vue.d.ts + │ └── ... + ├── package.json + ├── babel.config.js + └── ... + ``` + + - 文件命名:对于组件文件,推荐使用 'PascalCase' 的方式命名。例如:`MyComponent.vue`。而对于其它的 .js 或 .ts 文件,推荐使用 'kebab-case' 的方式命名。例如:`my-script.ts`。 +- 单文件组件的结构:template, script, style + 对于单文件组件(`.vue` 文件),其内部结构通常包含三部分:`