Vite这么香,你确定不来试试?Vite2.0+Vue3.0+Tsx 踩坑指南

2,103 阅读2分钟

安装Vite

兼容性注意 Vite 需要 Node.js 版本 >= 12.0.0

npm init @vitejs/app
# OR
yarn create @vitejs/app

创建项目

  • 通过附加的命令行选项直接指定项目名称和模板vue-ts
# npm 6.x
npm init @vitejs/app vite-ts --template vue-ts

# npm 7+, 需要额外的双横线:
npm init @vitejs/app vite-ts -- --template vue-ts

# yarn
yarn create @vitejs/app vite-ts --template vue-ts
  • 安装后,启动项目
cd vite-ts
npm install
npm run dev
  • 目录结构
├── public                     // public
├── src                        // 源代码
│   ├── assets                 // 静态资源
│   ├── components             // 全局公用组件
│   ├── App.vue                // 入口页面
│   └── main.ts                // 入口
├── index.html                 // html
├── .gitignore                 // git 忽略项
├── tsconfig.json              // ts 配置项
├── vite.config.ts             // vite 配置项
└── package.json               // package.json

安装插件

eslintprettier 语法检测

npm i -D eslint babel-eslint eslint-config-prettier eslint-plugin-prettier eslint-plugin-vue prettier @vue/eslint-config-prettier @typescript-eslint/eslint-plugin @typescript-eslint/parser 
  • 新建eslint 配置项:.eslintrc.js
module.exports = {
    root: true,
    env: {
        node: true,
    },
    extends: [
        "plugin:vue/vue3-essential",
        "eslint:recommended",
        "@vue/prettier",
    ],
    parserOptions: {
        parser: "babel-eslint",
    },
};
  • 新建编辑器配置格式:.editorconfig
root = true

[*]
charset = utf-8
indent_style = space
indent_size = 4
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true

less

npm i less -D

@vue/babel-plugin-jsx

  • Vue 3 JSX 和 TSX 语法支持。
npm i @vitejs/plugin-vue-jsx

Ant Design Vue 2.x

npm i --save ant-design-vue@next
  • 完整引入
import { createApp } from "vue";
import App from "./App.vue";
import Antd from "ant-design-vue";
import "ant-design-vue/dist/antd.css";
const app = createApp(App);
app.use(Antd);
app.mount("#app");

完整引入控制台会给出警告: You are using a whole package of antd, please use https://www.npmjs.com/package/babel-plugin-import to reduce app bundle size. Not support Vite !!!

  • 按需加载

注: babel-plugin-import按需加载不支持Vite,但是我们可以借助 vite-plugin-importer 插件。

  • 安装 vite-plugin-importer 实现按需加载: import { Button } from "ant-design-vue";
npm i vite-plugin-importer
  • 配置vite.config.ts
// vite.config.ts
import { defineConfig } from "vite";
import vue from "@vitejs/plugin-vue";
import vueJsx from "@vitejs/plugin-vue-jsx";
import viteImport from "vite-plugin-importer";
export default defineConfig({
    plugins: [
        vue(),
        vueJsx({
            // options are passed on to @vue/babel-plugin-jsx
        }),
        viteImport({
            libraryName: "ant-design-vue",
            libraryDirectory: "es",
            style: true,
        }),
    ],
    css: {
        preprocessorOptions: {
            less: {
                javascriptEnabled: true,
            },
        },
    },
});

Vue Router 4.x

npm install vue-router@4
// router/index.ts

import { createRouter, createWebHistory, RouteRecordRaw } from "vue-router";
const Login = () => import(/* webpackChunkName: "login" */ "../views/login");
const Layout = () => import(/* webpackChunkName: "layout" */ "../views/layout");
const Home = () => import(/* webpackChunkName: "home" */ "../views/home");
const NotFound = () => import(/* webpackChunkName: "NotFound" */ "../views/error/404");

const routes: RouteRecordRaw[] = [
    {
        path: "/",
        redirect: "/login",
        meta: {},
        component: Layout,
        children: [
            {
                name: "home",
                path: "home",
                meta: {
                    title: "首页",
                },
                component: Home,
            },
            {
                // 匹配 /home/xxx
                path: "/home:afterUser(.*)",
                component: NotFound,
            },
        ],
    },
    {
        name: "login",
        path: "/login",
        component: Login,
        meta: {
            title: "登录",
        },
    },
    {
        // 匹配 /xxx
        path: "/:pathMatch(.*)",
        component: NotFound,
    },
];
const router = createRouter({
    history: createWebHistory(),
    routes,
});
export default router;

到这,项目基本就搭建完毕了

Tsx 踩坑指南

  • @click="xxx" 改为:onClick={xxx}onClick={() => xxx("arg")}

  • 修饰符 @click.self="xxx"

import { withModifiers } from "vue";

<button onClick={withModifiers(submit, [ "self",])}>提交</button>
  • v-modle 单个: v-model={[foo, "value"]}

修饰符:v-model={[foo, "value", ["modifier"]]}

多个: v-modles

v-models={[
    [foo, ["modifier"]],
    [bar, "bar", ["modifier"]],
]}
  • v-if
setup() {
    const foo = ref<boolean>(true);
    return () => (
        <div>
            {
                foo.value && (
                    <div>
                        <span>foo</span>
                    </div>
                )
            }
        </div>
    )
}
  • v-for
setup() {
    const bars: string[] = ["bar1", "bar2"];
    return () => (
        <div>
            {
                bars.map((item) => (
                    <span>{item}</span>
                ))
            }
        </div>
    )
}
  • Slot 父组件
import { defineComponent } from "vue";
export default defineComponent({
    name: "name",
    setup(props, { slots }) {
        
        return () => (
            <div>
                <div>{ 
                    slots.default ? slots.default() : (
                        <span> foo </span>
                    ) 
                }</div>
                <div>{ slots.title?.() }</div>
            </div>
        )
    }
})

子组件

import { defineComponent } from "vue";
export default defineComponent({
    name: "name",
    setup(props, { slots }) {
        
        return () => (
            <div>{
                {
                    default: () => (
                        <span> foo </span>
                    ),
                    title: () => <span> title </span>
                }
            }</div>
        )
    }
})

// OR

import { defineComponent } from "vue";
export default defineComponent({
    name: "name",
    setup(props, { slots }) {
        const slots = {
            default: () => (
                <span> foo </span>
            ),
            title: () => <span> title </span>
        }
        return () => (
            <div v-slots={slots}></div>
        )
    }
})

⭐源码地址: github.com/Denny-di/vi…

有问题欢迎评论区指正~