尤大的 Vue3.0 已经发布有一阵子了, 已经很成熟了。今天想起来,是时候该上手体验分享一波了。
大家都知道,在 Vue3 生态系统中有一个新构建工具 Vite ,它的开发服务器比 Vue CLI 快 10 ~ 100倍,是不是很好奇?具体的内容可以移步至:迟到的 Vue3.0 与 Vite 的体验学习总结 的 七、Vite 与 Vue CLI 阅读。
本文将主要分享如何使用 Vite 来创建一个 Vue3.0 的项目,并且结合相关内容(TypeScript
、Vue Router
、Vuex
、Ant Design
等)编写一个简单的Demo。
npm install -g create-vite-app
create-vite-app vue3-vite
可以发现瞬间创建完成。
Done. Now run:
cd vue3-vite
npm install (or `yarn`)
npm run dev (or `yarn dev`)
根据提示安装依赖运行项目
C:\Users\jingx\Desktop\vite\vue3-vite>yarn dev
yarn run v1.22.10
warning package.json: No license field
$ vite
[vite] Optimizable dependencies detected:
vue
Dev server running at:
> Network: http://10.7.40.138:3000/
> Local: http://localhost:3000/
在项目中创建一个 vite.config.js
或 vite.config.ts
文件。如果在当前工作目录中找到 Vite,它将自动使用它。
vite.config.ts
基本配置:
const path = require("path")
function pathResolve(dir: string) {
return path(__dirname, ".", dir);
}
module.exports = {
// 服务端渲染
ssr: false,
// 是否开启 https
https: false,
// 设置目录别名
alias: {
// 键必须以斜线开始和结束
'/@/': pathResolve('/src'),
'/@components/': pathResolve('/src/components')
},
// 跨域设置
proxy: {
// 如果是 /api 开头,则访问如下地址
'/api': 'http://10.7.40.138:8080',
},
// 引入第三方的配置
optimizeDeps: {
include: ["moment", "echarts", "axios", "mockjs", "@ant-design/icons-vue"]
},
}
详细 config.ts 配置参考:Vite - config.ts
yarn add -D eslint eslint-plugin-vue
yarn add -D typescript
参考文档:
yarn add vue-router@next
yarn add vuex@@next
yarn add ant-design-vue@next
完整引入组件
import {
createApp } from 'vue'
import App from './App.vue'
import './index.css'
import Antd from 'ant-design-vue';
import 'ant-design-vue/dist/antd.css';
createApp(App).use(Antd).mount('#app');
以上代码便完成了 Antd
的引入。需要注意的是,样式文件需要单独引入。
注意:createApp(App).mount(’#app’).use(Antd)
.mount(’#app’) 和 .use(Antd) 的顺序一定不要写错,否则会报:createApp(…).mount(…).use is not a function 的错误。
这也是以为小伙伴提醒我的,非常感谢。
按需引入组件
# 需要使用 babel-plugin-import 来进行按需加载
yarn add -D babel-plugin-import
配置 .babelrc
文件
{
"plugins": [
["import", {
"libraryName": "ant-design-vue", "libraryDirectory": "es", "style": "css" }] // `style: true` 会加载 less 文件
]
}
# 按需加载需要的组件
import {
Button } from 'ant-design-vue';
yarn add -D sass
TypeScript
是 JavaScript
类型的超集,它可以编译成纯 js
。.js
文件更新成 .ts
文件即可,至于里面的细节内容可以去 TypeScript官网 阅读文档学习。ts
,其他内容都是相同的,本项目是为了体验 ts
才使用的,如果不使用可以直接省略。mian.js
重命名为 main.ts
,并且将项目中引用该文件的位置 index.html
也同步更新扩展名。新建文件: router/index.ts
用于配置路由信息
import {
createRouter, createWebHistory } from 'vue-router';
const routes = [
{
path: '/',
name: 'Login',
component: () => import("/@/views/Login.vue"),
}, {
path: '/Home',
component: () => import('/@/views/Home.vue'),
children: [
{
path: '/index',
component: () => import('/@/views/Index.vue'),
meta: {
title: '首页' },
},
{
path: '/admin',
component: () => import('/@/views/Admin.vue'),
meta: {
title: '状态管理' },
},
{
path: '/center',
component: () => import('/@/views/Center.vue'),
meta: {
title: '个人中心' },
}
]
}
]
export default createRouter({
history: createWebHistory(),
routes,
})
需要在 main.ts
中注入该路由信息。
可以在 .vue
页面中使用
、
等来使用路由。
Vuex 实例对象属性 主要有5个核心属性:state
、mutations
、getters
、actions
、modules
。具体使用就不再赘述了,使用方法大家跟 Vue2 的一样。
新建文件: store/index.ts
用于配置 vuex。其中state
、mutations
是一定要定义的,其他的三个属性对象根据实际需要。
import {
createStore } from 'vuex'
export default createStore({
state: {
count: 0,
},
getters: {
},
mutations: {
add(state) {
state.count++;
}
},
actions: {
add(ctx) {
ctx.commit('add')
}
},
modules: {
}
})
需要在项目的 main.ts
中将 Vuex
注册到全局实例中
在文件中使用:通过 this.$store.state.xxx
来获取状态的值,可以直接使用状态,也可以在vue计算属性 computed
中使用。在页面的具体使用见 Admin.vue
内容。
Login.vue
登录页面
<template>
<div class="login-wrap">
<div class="ms-login">
<div class="ms-title">后台管理系统</div>
<div class="ms-content">
<a-form layout="inline" :model="formInline" @submit="handleSubmit">
<a-form-item>
<a-input v-model:value="formInline.user" placeholder="Username">
<template #prefix
><UserOutlined style="color: rgba(0, 0, 0, 0.25)"
/></template>
</a-input>
</a-form-item>
<a-form-item>
<a-input
v-model:value="formInline.password"
type="password"
placeholder="Password"
>
<template #prefix
><LockOutlined style="color: rgba(0, 0, 0, 0.25)"
/></template>
</a-input>
</a-form-item>
<a-form-item>
<a-button
type="primary"
html-type="submit"
:disabled="formInline.user === '' || formInline.password === ''"
>
Log in
</a-button>
</a-form-item>
</a-form>
</div>
</div>
</div>
</template>
<script>
import {
UserOutlined, LockOutlined } from "@ant-design/icons-vue";
import {
reactive, getCurrentInstance } from "vue";
import {
message } from "ant-design-vue";
export default {
setup() {
const formInline = reactive({
username: "",
password: "",
});
const {
ctx } = getCurrentInstance();
const handleSubmit = () => {
message.info("登录成功!");
setTimeout(() => {
ctx.$router.push("/index");
}, 1000);
};
return {
formInline,
handleSubmit,
};
},
components: {
UserOutlined,
LockOutlined,
},
};
</script>
<style scoped>
// .... 具体代码见 Github
</style >
Home.vue
后台页面
<template>
<a-layout id="components-layout-demo-custom-trigger">
<a-layout-sider v-model:collapsed="collapsed" :trigger="null" collapsible>
<div class="logo">
<span>后台管理中心</span>
</div>
<a-menu theme="dark" mode="inline" v-model:selectedKeys="selectedKeys">
<a-menu-item key="1">
<router-link :to="{ path: '/index' }">首页</router-link>
</a-menu-item>
<a-menu-item key="2">
<router-link :to="{ path: '/admin' }">状态管理Vuex</router-link>
</a-menu-item>
<a-menu-item key="3">
<router-link :to="{ path: '/center' }">个人中心</router-link>
</a-menu-item>
</a-menu>
</a-layout-sider>
<a-layout>
<a-layout-header style="background: #fff; padding: 0">
<menu-unfold-outlined
v-if="collapsed"
class="trigger"
@click="() => (collapsed = !collapsed)"
/>
<menu-fold-outlined
v-else
class="trigger"
@click="() => (collapsed = !collapsed)"
/>
</a-layout-header>
<a-layout-content
:style="{
margin: '24px 16px',
padding: '24px',
background: '#fff',
minHeight: '280px',
}"
>
<router-view></router-view>
</a-layout-content>
</a-layout>
</a-layout>
</template>
<script>
import {
UserOutlined,
VideoCameraOutlined,
UploadOutlined,
MenuUnfoldOutlined,
MenuFoldOutlined,
} from "@ant-design/icons-vue";
export default {
components: {
UserOutlined,
VideoCameraOutlined,
UploadOutlined,
MenuUnfoldOutlined,
MenuFoldOutlined,
},
data() {
return {
selectedKeys: ["1"],
collapsed: false,
};
},
};
</script>
<style scoped>
// .... 具体代码见 Github
</style >
Index.vue
后台首页
<template>
<img class="img" src="https://ss0.bdstatic.com/70cFuHSh_Q1YnxGkpoWK1HF6hhy/it/u=2685630714,1375929910&fm=26&gp=0.jpg" alt="" srcset="">
</template>
Admin.vue
状态管理页面Vuex
<template>
<h2>通过 Vuex 实现状态管理</h2>
<h3>state from vuex: {
{
count }}</h3>
<br />
<a-button type="primary" @click="add">add</a-button>
</template>
<script>
import {
computed, getCurrentInstance } from "vue";
export default {
setup() {
const {
ctx } = getCurrentInstance();
const count = computed(() => ctx.$store.state.count);
const add = () => {
ctx.$store.commit("add");
};
return {
count,
add,
};
},
};
</script>
import {
createApp } from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
import './styles/index.scss'
import Antd from 'ant-design-vue';
import 'ant-design-vue/dist/antd.css';
const app = createApp(App)
app.mount('#app')
app.use(Antd)
app.use(router)
app.use(store)
找不到模块“xxx”或其相应的类型声明。ts(2307)
的错误,该解决方案请移至文章末尾查看。<template>
<div id="app">
<router-view></router-view>
</div>
</template>
<script></script>
<style>
@import "./styles/index.scss";
</style>
原因:typescript
只能理解 .ts
文件,无法理解 .vue
文件
解决方案:在项目根目录或 src 文件夹下创建一个后缀为 .d.ts
的 shims-vue.d.ts
文件,告诉 TS 如何理解 .vue 文件
,并写入以下内容:
declare module '*.vue' {
import {
ComponentOptions } from 'vue'
const componentOptions: ComponentOptions
export default componentOptions
}
在次查看之前报错的地方,错误消失,问题解决。
如果写了这个还是报错的话,新建一个 tsconfig.json
文件,也可以解决不需要总是打开 shims-vue.d.ts
来解决 TS 报错的问题
{
"compilerOptions": {
"target": "esnext",
"module": "esnext",
"strict": false,
"jsx": "preserve",
"moduleResolution": "node"
}
}
至此,一个基本完整的小项目搭建完成,大家可以根据自己的需求进行项目的实际开发。
Vite2.0 已经发布了,如果想看一下具体内容,请参考:vite1.0还没学呢 这就出2.0了?