• 基于vue3+ts5+vue-router4+pinia2的PC端项目搭建教程


    导语:在日常开发中,有时候会在项目中引入 ts 来解决一些 js 的问题,下面就简单介绍一下如何使用 vue3+ts+router+pinia 来搭建一个项目。

    目录

    • 简介
    • 创建
    • 安装
    • 配置
    • 实战

    简介

    vue3 目前是常用的 vue 版本,提供了组合式 API 以及一些新的功能和特性;ts 这种类型编程语言可以在编译时通过静态分析检测出很多常见错误,减少了生产环境中的运行时错误,改善了开发体验和效率;vue-router 也更新到了 4 版本,pinia 则是最新退出的替代 vuex 的一个 vue 官方状态管理库;下面就结合以上提到的技术栈组合来简单创建一个项目。

    创建

    下面打开 cmd 或其他命令行,输入以下命令创建一个 vite 项目。

    这里我选择使用pnpm来创建。

    • 创建 vite 项目
    pnpm create vite
    
    • 1
    • 填写项目信息

    包括项目名称、选择框架、js 语言等。

    √ Project name: ... tslx
    √ Select a framework: » Vue
    √ Select a variant: » TypeScript
    
    • 1
    • 2
    • 3
    • 创建成功

    根据以下步骤来安装基本的依赖和运行项目。

    cd tslx
    pnpm install
    pnpm run dev
    
    • 1
    • 2
    • 3

    安装

    创建好项目后,接下来安装一些必备的依赖包。

    必备依赖包

    • vue-router

    这个是必须的,路由管理。

    pnpm i vue-router -S
    
    • 1
    • sass

    这个是必须的,主要是使用 sass 写项目样式表。

    pnpm i sass -S
    
    • 1
    • axios

    这个是必须的,主要是 http 请求数据。

    pnpm i axios -S
    
    • 1

    可选依赖包

    • pinia

    这个是可选的,主要是提供状态管理。

    pnpm i pinia -D
    
    • 1
    • pinia-plugin-persist

    这个是可选的,主要是提供状态管理的持久化存储。

    pnpm i pinia-plugin-persist -D
    
    • 1
    • unplugin-auto-import

    这个是可选的,自动导入依赖插件。

    pnpm i unplugin-auto-import -D
    
    • 1
    • normalize.css

    这个是可选的,主要是可定制化 CSS 样式。

    pnpm i normalize.css -D
    
    • 1
    • mitt

    这个是可选的,一个简洁、灵活的 JavaScript 事件订阅和发布库。

    pnpm i mitt -D
    
    • 1
    • @volar-plugins/vetur

    这是可选的,一个支持 vue3 语法的插件。

    pnpm i @volar-plugins/vetur -D
    
    • 1
    • @vitejs/plugin-vue

    这个是可选的,支持基于 Vite 构建的 Vue 项目。

    pnpm i @vitejs/plugin-vue -D
    
    • 1
    • @types/node

    这个是可选的,主要是解决模块的声明问题。

    pnpm i @types/node -D
    
    • 1
    • path

    这个是可选的,主要是 node 的 path 模块。

    pnpm i path -D
    
    • 1
    • rollup-plugin-visualizer

    这个是可选的,主要是应用模块统计。

    pnpm i rollup-plugin-visualizer -D
    
    • 1
    • vue-i18n

    这个是可选的,主要是多语言配置。

    pnpm i vue-i18n -D
    
    • 1

    好了,以上就是日常开发项目常用的一些依赖包。

    配置

    下面配置一下vite.config.ts文件和main.ts文件以及其他需要配置的文件。

    vite 配置文件

    打开vite.config.ts文件,主要是添加插件配置,文件路径别名配置,css 全局样式配置,服务端端口及代理配置。

    引入依赖
    import AutoImport from "unplugin-auto-import/vite";
    import vetur from "@volar-plugins/vetur";
    import path from "path";
    import { visualizer } from "rollup-plugin-visualizer";
    
    • 1
    • 2
    • 3
    • 4
    插件配置

    plugins中添加以下配置。

    //...
    {
      plugins: [
        vue({
          template: {
            compilerOptions: {
              isCustomElement: () => {
                return false;
              },
            },
          },
        }),
        vetur,
        AutoImport({
          dts: "src/auto-import.d.ts",
          include: [
            /\.[tj]sx?$/, // .ts, .tsx, .js, .jsx
            /\.vue$/,
            /\.vue\?vue/, // .vue
          ],
          imports: [
            "vue",
            "vue-router",
            {
              from: "vue-router",
              imports: ["RouteLocationRaw"],
              type: true,
            },
          ],
        }),
        visualizer({
          emitFile: false,
          filename: "stats.html",
          open: true,
        }),
      ];
    }
    // ...
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    文件路径别名配置

    src文件夹下面新建三个文件,可以选择去掉assets文件夹。

    • types:主要是存放 ts 声明等内容;
    • styles:主要是存放全局样式文件;
    • apis:主要是存放全局方法文件;

    下面是配置方法。

    //...
    {
      resolve: {
        alias: {
          "@": path.resolve(__dirname, "./src"),
          "@c": path.resolve(__dirname, "./src/components"),
          "@t": path.resolve(__dirname, "./src/types"),
          "@s": path.resolve(__dirname, "./src/styles"),
          "@a": path.resolve(__dirname, "./src/apis"),
        },
      }
    }
    //...
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    css 全局样式配置

    下面设置 css 全局样式配置,在刚刚创建的styles文件夹下面创建一个global.scss的文件。

    // ...
    {
      css: {
        preprocessorOptions: {
          scss: {
            additionalData: '@import "./src/styles/global.scss";',
            javascriptEnabled: true,
          },
        },
      },
    }
    //...
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    服务端端口及代理配置

    最后就是一个服务端的配置,包括端口,自动打开网页,跨域接口设置。

    //...
    {
      server: {
        host: "0.0.0.0",
        port: 6060,
        open: true,
        proxy: {
          "/api": {
            autoRewrite: true,
            target: "http://127.0.0.1:9999",
            changeOrigin: true,
            ws: true,
          },
        },
      },
    }
    //...
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    配置好以后,重启一下服务就生效了。

    配置 ts

    • 添加paths路径

    tsconfig.json中新增一个paths属性并配置如下。

    {
      "paths": {
        "@/*": ["src/*"],
        "@c/*": ["src/components/*"],
        "@t/*": ["src/types/*"],
        "@s/*": ["src/styles/*"],
        "@a/*": ["src/apis/*"]
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 完整配置

    完整的tsconfig.json内容:

    {
      "compilerOptions": {
        "target": "ESNext",
        "useDefineForClassFields": true,
        "module": "ESNext",
        "lib": ["ESNext", "DOM", "DOM.Iterable"],
        "skipLibCheck": true,
    
        /* Bundler mode */
        "moduleResolution": "Node",
        "allowImportingTsExtensions": true,
        "resolveJsonModule": true,
        "isolatedModules": true,
        "noEmit": true,
        "jsx": "preserve",
    
        /* Linting */
        "strict": true,
        "noUnusedLocals": true,
        "noUnusedParameters": true,
        "noFallthroughCasesInSwitch": true
      },
      "include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"],
      "references": [{ "path": "./tsconfig.node.json" }],
      "paths": {
        "@/*": ["src/*"],
        "@c/*": ["src/components/*"],
        "@t/*": ["src/types/*"],
        "@s/*": ["src/styles/*"],
        "@a/*": ["src/apis/*"]
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    完整的tsconfig.node.json的内容:

    {
      "compilerOptions": {
        "composite": true,
        "skipLibCheck": true,
        "module": "ESNext",
        "moduleResolution": "Node",
        "allowSyntheticDefaultImports": true
      },
      "include": ["vite.config.ts"]
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    配置 main.ts

    • 整理main.ts文件

    修改为以下内容,这样方便后面挂载全局组件,方法和插件等内容。

    import { createApp } from "vue";
    import App from "./App.vue";
    
    const app = createApp(App);
    
    app.mount("#app");
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • vue 组件声明

    打开main.ts会看到找不到模块“./App.vue”或其相应的类型声明的报错,下面就在src下面新建一个 vue 声明文件global.d.ts

    // ./src/global.d.ts
    declare module "*.vue" {
      import type { DefineComponent } from "vue";
      const vueComponent: DefineComponent<{}, {}, any>;
      export default vueComponent;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    这个可以让 ts 识别 vue 组件类型声明。

    配置 vue-router

    下面简单的配置一个路由文件,在src下面新建一个router文件夹,并创建一个index.ts文件。

    // ./src/router/index.ts
    
    // 导入依赖
    import { createRouter, createWebHistory, RouteRecordRaw } from "vue-router";
    
    // 配置routes
    const routes: Array<RouteRecordRaw> = [
      {
        path: "/",
        name: "Home",
        component: () => import("@c/home.vue"),
        children: [],
      },
      {
        path: "/404",
        name: "NotFound",
        component: () => import("@c/404.vue"),
        meta: {
          title: "404",
          auth: false,
        },
      },
      {
        path: "/:pathMatch(.*)",
        redirect: "/404",
      },
    ];
    
    // 配置router
    const router = createRouter({
      history: createWebHistory(),
      routes,
      scrollBehavior(to, from) {
        console.log(to, from);
        return {
          left: 0,
          top: 0,
        };
      },
    });
    
    // 配置钩子
    router.beforeEach((to, from, next) => {
      console.log(to, from);
      // ...
      next();
    });
    
    router.afterEach((to, from) => {
      console.log(to, from);
      // window.scrollTo(0, 0);
    });
    
    // 导出路由
    export default router;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 导入main.ts文件。
    //...
    import router from "./router";
    // ...
    app.use(router);
    //...
    
    • 1
    • 2
    • 3
    • 4
    • 5

    配置 pinia

    src下面新建一个store的文件夹,里面新建一个index.tstypes.ts以及user.ts的文件。

    • index.ts文件

    这个文件主要是放置基础的配置,包括插件,持久化存储。

    import { createPinia } from "pinia";
    import piniaPluginPerisit from "pinia-plugin-persist";
    
    // 全局设置
    export const pinia = createPinia();
    pinia.use(piniaPluginPerisit);
    
    export default pinia;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    在配置的时候,pinia-plugin-persist插件可能会报错,原因是找不到模块声明。

    可以采取以下方法解决:

    1. 升级到最新版试试看;
    2. types目录下新建一个pinia-plugin-persist.d.ts声明文件。

    内容为:

    declare module "pinia-plugin-persist";
    
    • 1
    • types.ts文件

    这个文件主要是放置类型变量。

    const enum NAMES {
      user = "USER",
    }
    
    export default NAMES;
    
    • 1
    • 2
    • 3
    • 4
    • 5

    enum可能会报错,Parsing error: The keyword 'enum' is reserved, enum 是 Javascript 为未来特性保留的关键字,我们不应该使用它,属于eslint检查错误。

    可以采取以下方法解决:

    安装三个插件eslint-plugin-vue@typescript-eslint/parser@typescript-eslint/eslint-plugin;

    pnpm i eslint-plugin-vue @typescript-eslint/parser @typescript-eslint/eslint-plugin -D
    
    • 1

    修改项目根目录下的.eslintrc.json配置文件;

    {
      "env": {
        "browser": true,
        "es2021": true,
        "node": true,
        "vue/setup-compiler-macros": true
      },
      "extends": [
        "plugin:vue/vue3-essential",
        "eslint:recommended",
        "prettier",
        "plugin:@typescript-eslint/recommended"
      ],
      "parser": "vue-eslint-parser",
      "parserOptions": {
        "ecmaVersion": "latest",
        "sourceType": "module",
        "parser": "@typescript-eslint/parser"
      },
      "plugins": ["vue", "prettier"],
      "rules": {
        "semi": ["warn", "never"]
      },
      "settings": {}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    重启一下项目就可以了。

    • user.ts文件

    这个文件主要是用户的一些状态信息。

    import { defineStore } from "pinia";
    import NAMES from "./types";
    import { User } from "../types/interface";
    
    // 用户
    const user = defineStore(NAMES.user, {
      state: () => {
        return {
          userInfo: {
            id: 1,
            name: "mark",
          },
        };
      },
      getters: {
        getUserInfo(state) {
          return state.userInfo;
        },
      },
      actions: {
        saveUser(user: User) {
          this.userInfo = user;
        },
      },
    });
    
    export default user;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    上面简单做了个interface的接口定义。

    // ./src/types/interface.ts
    // 用户信息
    export interface User {
      id: number;
      name: string;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 导入main.ts文件。
    //...
    import pinia from "./store";
    // ...
    app.use(pinia);
    //...
    
    • 1
    • 2
    • 3
    • 4
    • 5

    配置 vue-i18n

    src文件夹下面新建locale文件夹,用了存放vue-i18n配置信息。

    包括zhCn.tszhHk.tsen.tslang.tsindex.ts等文件。

    语言内容
    • 中文简体 zhCn
    const zhCn = {
      home: "首页",
      index: "主页",
      list: "列表",
      info: "信息",
      welcome: "欢迎光临",
    };
    
    export default zhCn;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 中文繁体 zhHk
    const zhHk = {
      home: "首頁",
      index: "主頁",
      list: "清單",
      info: "資訊",
      welcome: "歡迎光臨",
    };
    
    export default zhHk;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 英文 en
    // 英文
    const en = {
      home: "Home",
      index: "Index",
      list: "List",
      info: "Info",
      welcome: "Welcome",
    };
    
    export default en;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    配置index.ts
    • 导入lang.ts
    import zhCn from "./zhCn";
    import zhHk from "./zhHk";
    import en from "./en";
    
    export default {
      zhCn,
      zhHk,
      en,
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 导入index.ts
    import { createI18n } from "vue-i18n";
    import messages from "./lang";
    
    const i18n: any = createI18n({
      locale: localStorage.getItem("lang") || "zhCn",
      globalInjection: true,
      legacy: false,
      messages,
    });
    
    export default i18n;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • tsconfig.json中添加类型
    {
      "compilerOptions": {
        // ...
        "types": ["vue-i18n"]
      }
      // ...
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    全局引入

    main.ts中引入vue-i18n

    // ...
    import i18n from "./locale/index";
    // ...
    app.config.globalProperties.$i18n = i18n;
    // ...
    app.use(i18n);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    接下来就可以在组件或者其他 ts 文件中使用了。

    配置全局样式

    styles文件夹中新建一个font.scssreset.css样式文件,然后导入main.ts文件中即可实现。

    // ./src/main.ts
    import "@s/reset.css";
    import "@s/font.scss";
    
    • 1
    • 2
    • 3

    配置全局方法

    • http 方法

    apis文件夹中新建一个http.ts文件,封装请求方法。

    // ./src/apis/http.ts
    import axios from "axios";
    
    // 创建axios实例
    const http = axios.create({
      baseURL: "/",
      timeout: 30000,
      headers: {
        "Content-Type": "application/json",
      },
    });
    
    // 请求拦截
    http.interceptors.request.use(
      (config) => {
        config.headers.version = "v1";
        return config;
      },
      (err) => {
        return Promise.reject(err);
      }
    );
    
    // 响应拦截
    http.interceptors.response.use(
      (res) => {
        let data = res.data;
        return data;
      },
      (err) => {
        return Promise.reject(err);
      }
    );
    
    export default http;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • util 方法

    apis文件夹中新建一个util.ts文件,封装请求方法。

    // ./src/apis/util.ts
    // 全局方法
    import { AllAny } from "../types/interface";
    
    const sum = (a: number, b: number): number => a + b;
    
    const util: AllAny = {
      sum,
    };
    
    export default util;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    这里我又定义了util的接口。

    // 任意对象类型
    export interface AllAny {
      [propsName: string]: any;
    }
    
    • 1
    • 2
    • 3
    • 4
    • mitt 方法

    下面介绍以下如何配置mitt

    apis文件夹下面新建一个mitts.ts文件。

    // ./src/apis/mitts.ts
    import mitt, { Emitter } from "mitt";
    import { MittEvents } from "../types/interface";
    
    const mitts: Emitter<MittEvents> = mitt<MittEvents>();
    
    export default mitts;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    记得在interface.ts声明以下类型。

    // mitt类型
    export type MittEvents = {
      [propsName: string]: any;
    };
    
    • 1
    • 2
    • 3
    • 4
    • 导入main.ts文件
    // ./src/main.ts
    // ...
    import http from "./apis/http";
    import util from "./apis/util";
    import mitts from "./apis/mitts";
    // ...
    app.config.globalProperties.$http = http;
    app.config.globalProperties.$util = util;
    app.config.globalProperties.$mitts = mitts;
    // ...
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    实战

    在项目创建,安装依赖,配置全局环境结束后,写一个简单的组件案例。

    组件组成

    
    
    
    
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    小案例

    下面是home.vue组件中的一些小案例,可以练习一下。

    • 模板内容
    
    <p>
      <span>{{ sayHi }}span>
    p>
    <p>
      <button type="button" @click="changeName">改变姓名button>
    p>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    
    <p>
      <button type="button" @click="goNotFound">到404button>
    p>
    
    • 1
    • 2
    • 3
    • 4
    
    <p>
      <button type="button" @click="getData">请求接口button>
    p>
    <p>接口数据:{{ msg }}p>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    
    <p>
      <input v-model="sumInfo.num1" type="number" name="num1" id="num1" placeholder="数字1" />+
      <input v-model="sumInfo.num2" type="number" name="num2" id="num2" placeholder="数字2" />= {{
      sumInfo.sum }}
    p>
    <p>
      <button type="button" @click="getSum">计算和button>
    p>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    
    <p>
      <button type="button" @click="sendMsg">发送消息button>
    p>
    
    • 1
    • 2
    • 3
    • 4
    • 引入依赖
    import { reactive, ref, watch, computed } from "vue";
    import { useRoute, useRouter } from "vue-router";
    import userStore from "../store/user";
    import { Store } from "pinia";
    import { useCurrentInstance } from "../types/util";
    import { AllAny } from "../types/interface";
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    useCurrentInstance方法在../types/util.ts文件中定义一下即可。

    //../types/util
    import { ComponentInternalInstance, getCurrentInstance } from "vue";
    
    export function useCurrentInstance() {
      const instance = getCurrentInstance();
      const { appContext } = instance as ComponentInternalInstance;
      const app = instance as any;
      const proxy = appContext.config.globalProperties;
      return {
        proxy,
        app,
      };
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 定义数据
    // 组件路由
    const route = useRoute();
    const router = useRouter();
    console.log("route:", route, router);
    
    // 用户状态
    const user: Store = userStore();
    console.log("store:", user);
    
    // 组件数据
    const msg: Ref = ref("");
    console.log("data:", msg);
    
    const info = reactive({
      id: 1,
      name: "mark",
    });
    console.log("data:", info);
    
    const sumInfo = reactive({
      num1: 0,
      num2: 0,
      sum: 0,
    });
    
    console.log("sum:", sumInfo);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 定义方法
    // 组件监听
    watch(
      () => [info.name],
      (val: string[]) => {
        console.log("watch:", val);
      }
    );
    
    // 组件计算
    const sayHi = computed(() => {
      return `Hi,${info.name}!`;
    });
    
    // 组件当前实例
    const { proxy } = useCurrentInstance();
    console.log("proxy:", proxy);
    
    // 改变姓名
    function changeName() {
      info.name = "jack";
    }
    
    // 到404
    function goNotFound() {
      router.push("/404");
    }
    
    // 请求接口
    async function getData() {
      let data: AllAny = await proxy.$http.get("/todos/1");
      msg.value = data;
      console.log("http:", data);
    }
    
    // 计算和
    function getSum() {
      let sum: number = proxy.$util.sum(sumInfo.num1, sumInfo.num2);
      sumInfo.sum = sum;
    }
    
    // 发送消息
    function sendMsg() {
      proxy.$mitts.emit("user", "mark");
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44

    多语言案例

    • 路由使用
    import i18n from "../locale/index";
    const trans = i18n.global.t;
    
    trans("home");
    
    • 1
    • 2
    • 3
    • 4
    • 组件使用
    import { useI18n } from "vue-i18n";
    const { t } = useI18n();
    
    console.log(t("welcome"));
    
    • 1
    • 2
    • 3
    • 4

    以上就是如何从零搭建一个 vue3+ts5+vue-router4+pinia2 的项目方法。

  • 相关阅读:
    软件运维常见面试题
    离线数仓-用户行为采集
    基于JavaSwing开发自选拼图游戏 课程设计 大作业
    黑盒不黑:跨端 C/C++ 库一键源码调试方案
    【氮化镓】GaN HEMT SEEs效应影响因素和机制
    dcatadmin批量操作时异步请求获取当前选中的id
    sql order by 排序 null值放最后,怎么写
    【LeetCode】39、组合总和
    我为什么要推荐用Stream语法
    解决redis在centos上部署
  • 原文地址:https://blog.csdn.net/fed_guanqi/article/details/133934226