Vite is an opinionated web dev build tool that serves your code via native ES Module imports during dev and bundles it with Rollup for production.
目前,Vue-cli 还未能直接搭建 vue3 应用,需要在 vue2 的项目上通过执行vue add next
命令进行升级。
而 Vite 是官方提供的一个可以快速搭建 vue3 新工具,它是一个简易的 http 服务器,无需通过 webpack 打包即可实时解析 vue3 文件,并能实现热更新。
现在最新版的 vite 已经提供了一个简易模板,可以直接使用一下命令快速搭建
$ npx create-vite-app <project-name>
$ cd <project-name>
$ npm install
$ npm run dev
具体参考官方仓库: https://github.com/vuejs/vite#getting-started
vite 最新版默认已经可以直接对 typescript 进行解析编译,直接在 vue 文件中的script
标签下加入lang="ts"
即可。
执行命令安装 sass, npm i sass -D
, 然后在 vue 文件的style
标签下加入lang="scss"
即可,这些与以前 vue2 都是一样的。
支持 vue3 的 vuex 最新版现在还未正式发版,需要使用npm i vuex@next -D
来安装。
Vuex 的新语法进行了一些变更,你需要使用 Vuex.createStore 来创建,其他语法没有区别。
import Vuex from "vuex";
// or => import { createStore } from 'vuex'
export default Vuex.createStore({
state: {},
mutations: {},
actions: {},
modules: {},
});
然后在 main.js 引入这个文件并 use
import { createApp } from "vue";
import App from "./App.vue";
import store from "./store/index.js";
import "./assets/base.css";
createApp(App).use(store).mount("#app");
Vue3 最大的一个变化就是使用Vue Compostion Api
, 现在官方已经提供了 中文文档
本次只用到了其中很少一部分的 API,而且可能使用方式不一定准确,仅供参考,望见谅。
现在先来看一下最终项目 DEMO 成果
点击头部的日期会弹出日期选择,可选择其他日期。
主要组件Card.vue
组件,然后里面包含一个日期选择组件DatePicker.vue
为了练习一下 vuex 在 vue3 的使用,将当前的选择日期记录在了 vuex 中。
主要逻辑代码
// Card.vue
import { ref, reactive, computed, watch } from "vue";
import { useStore } from "vuex";
import { Todo, getTodoList, setTodoList } from "../model/todo";
import DatePicker from "./DatePicker.vue";
const weekArr: string[] = [
"Sunday",
"Monday",
"Tuesday",
"Wednesday",
"Thursday",
"Firday",
"Saturday",
];
export default {
name: "Card",
components: {
DatePicker,
},
directives: {
focus(el) {
el.focus();
},
},
props: {
date: String,
showAddBtn: Boolean,
},
setup(props) {
const store = useStore();
const state = {
editingValue: ref(""),
showDatePicker: ref(false),
};
let todoList = reactive([]);
watch(
() => props.date,
(val) => {
todoList.length = 0;
todoList.push(...getTodoList(props.date));
// state.showDatePicker.value = false
},
{
immediate: true,
}
);
const weekDay = computed(() => weekArr[new Date(props.date).getDay()]);
const formatterDate = computed((): string => {
const arr: string[] = new Date(props.date).toDateString().split(" ");
return `${arr[1]} ${arr[2]}, ${arr[3]}`;
});
const handleChecked = (item: Todo): void => {
item.isChecked = !item.isChecked;
setTodoList(props.date, todoList);
store.commit("refreshTodoListDateArr");
};
const handleRemove = (index: number): void => {
todoList.splice(index, 1);
setTodoList(props.date, todoList);
store.commit("refreshTodoListDateArr");
};
const handleAdd = (): void => {
state.editingValue.value = "";
todoList.push({
content: "",
isChecked: false,
isEditing: true,
});
};
const handleEditSubmit = (item: Todo, index: number): void => {
if (item.isEditing) {
if (state.editingValue.value) {
item.content = state.editingValue.value;
item.isEditing = false;
} else {
todoList.splice(index, 1);
}
setTodoList(props.date, todoList);
store.commit("refreshTodoListDateArr");
}
};
return {
weekDay,
formatterDate,
todoList,
handleChecked,
handleRemove,
handleAdd,
handleEditSubmit,
...state,
};
},
};
组件功能实现都比较简单,本次只为了熟悉语法,所以具体代码逻辑在这就不进行讲解了。
使用npm run build
或者npx vite build
即可打包项目。
Vite 的打包基于 Rollup
需要注意的是,vite 也是想 vue-cli 那样提供了配置文件的,在根目录下添加vite.config.js
即可,例如本地打包后项目是通过 https://kongfandong.cn/todo 来访问的,如果使用默认的打包配置,会出现资源 404 的问题。这时需要给打包配置资源路径/todo
,加入以下配置:
// vite.config.js
module.exports = {
base: "/todo",
};
Vite 还提供了很多其他的配置,具体请参考: https://github.com/vuejs/vite/blob/master/src/node/config.ts
一开始,我使用 vuex 是使用getCurrentInstance
获取 vue 的实例想像 vue2 那样类似this.$store.state
来使用 vuex 的,就像下面的代码
import { computed, getCurrentInstance } from "vue";
export default {
setup() {
const { ctx } = getCuurentInstance();
const selectedDate = computed(() => ctx.$store.state.selectedDate);
return {
selectedDate,
};
},
};
这样 ts 会报错,提示 ctx 的类型没找到,通过查源码发现 vue 并没有把 ctx 的类型抛出。然后我就改成了
import { computed, getCurrentInstance } from "vue";
export default {
setup() {
const instance: any = getCuurentInstance();
const ctx = instance.ctx;
const selectedDate = computed(() => ctx.$store.state.selectedDate);
return {
selectedDate,
};
},
};
然后一切如愿进行,开发环境下什么问题也没有了。但是,到了打包之后运行,浏览器就报错了
index.js:9 Uncaught TypeError: Cannot read property 'state' of undefined
at index.js:9
at n (index.js:1)
at Object.get value [as value] (index.js:1)
at Object.get (index.js:1)
at Object.get (index.js:1)
at index.js:9
at Vn (index.js:1)
at Proxy.<anonymous> (index.js:9)
at Proxy.<anonymous> (index.js:1)
at nt (index.js:1)
(anonymous) @ index.js:9
...
报错 state 没找到,程序上的 vuex 的$store 是 undefined。然后我查了好久也没找到解决办法,于是只能在 github 上提个 issue。
最后得到了解答,原来在setup()
中是不能使用getCurrentInstance
的!
具体 Issue: https://github.com/vuejs/vite/issues/156
最终的解决办法,引入 vuex 的 useStore 方法,就可以在 setup 中使用 vuex 了。
最后代码改为:
import { computed } from "vue";
import { useStore } from "vuex";
export default {
setup() {
const store = useStore();
const selectedDate = computed(() => ctx.$store.state.selectedDate);
return {
selectedDate,
};
},
};
这个小 Demo 的实现过来还是遇到了不少问题,但还是一一解决了,可以让我对 vue3 与 typescript 进行了初步的了解。目前只是因为还不太熟悉,但感觉 vue3 未来发展潜力还是很大的。
还有 Vite 这个工具好像也是很强大的,目测 Vue3 官方后面有可能会直接推荐使用该工具进行开发了,有可能会放弃的 Webpack 了。