2022全面升级 Vue3 + TS 仿知乎专栏企业级项目完整wumi

172 阅读4分钟

 03915cbcf7644abf2ed1da62b1c52a96.jpeg​编辑

##download: 2022全面升级!Vue3 + TS 仿知乎专栏企业级项目

Vue3全家桶vue-router和vuex使用

引入router很简单,创建一个VueRouter的实例,最重要的两个参数一个就是路由模式,一个就是路由配置(见下),创建好以后,扔到Vue实例的配置中就行,最终路由的所有相关信息都会挂在this.router上,组件可以通过this.router上,组件可以通过this.router直接访问。

require('es6-promise').polyfill(); //es6 promise
require('isomorphic-fetch'); //fetch库

import Vue from 'vue';
import VueRouter from 'vue-router';
import routes from './route-config.js'; //路由配置
import store from './store/index.js'; //store
import App from './views/App.vue'; //页面容器

Vue.use(VueRouter); //vue使用veux,vue-router 都是通过Vue这个对象上的use这个方法。

//创建路由
const router = new VueRouter({
mode: 'hash', //路由的模式
routes
});

//将store, router加入并生成应用
new Vue({
el: '#application',
store,
router,
render: h => h(App)
});
src/route-config.js
路由配置也很简单,文档有详细的例子。如果应用过大,打包到一个js文件里有点不合适,我们可以在这里引入页面的时候做页面的懒加载,就是code spliting。懒加载例子

import HomePage from './views/HomePage.vue'; //引入页面
import CounterPage from './views/CounterPage.vue';

//当然真正应用的路由不会这么简单,vue-router也提供动态路由,嵌套路由等等,详见vue-router文档
export default [
{ path: '/', component: HomePage },
{ path: '/counter', component: CounterPage}
];
src/store/index.js
同使用vue-router一样,先调一下use方法,然后新建一个Store实例,把state,actions,getters,mutations全扔进去。

最终将store抛出,会被用在新建vue实例的时候。同样store的所有相关会挂在this.store上,组件可以通过this.store上,组件可以通过this.store直接访问。

import Vue from 'vue';
import Vuex from 'vuex';
import actions from './actions/index.js';
import mutations from './mutations/index.js';
import * as getters from './getters/index.js';

Vue.use(Vuex);

//state
const state = {
count: 0, //counter actions 操作的值
pageData: {} //fetch action 操作的值
};

//把上面的融到一起
export default new Vuex.Store({
state,
actions,
getters,
mutations
});
src/views/App.vue

Vue3完成自定义Form组件

父子组件
插槽的用法-slot
跨组件传值-provide
跨组件通信--mmit
自定义props
自定义事件

首先我们定义一个父级容器存放我们所有的组件

定义父级容器的props
···
props: {
model: {
type: Object,
},
rules: {
type: Object,
},
}
···
定义父级容器的方法
emits: ["finish"],

复制代码
定义父级容器的校验方法

setup(props, ctx) {
const formMapKey = {};
for (let k of Object.keys(props.rules)) {
formMapKey[k] = true;
}
const formState = reactive(formMapKey);
// formState.username = false;
const validated = computed(() => {
let res = true;
for (let k in formMapKey) {
res = res && formMapKey[k];
}
return res;
});

const validate = (k) => {
let rules = null;
let model = null;
if (k === "") {
rules = props.rules;
model = props.model;
} else {
rules = { [k]: props.rules[k] };
model = { [k]: props.model[k] };
}
const validator = new Schema(rules);
const handleErrors = (errors, fields) => {
VueEvent.emit("validate", fields);
const keySet = new Set(Object.keys(fields));
for (let k in formState) {
if (keySet.has(k)) {
formState[k] = false;
} else {
formState[k] = true;
}
}
};
validator
.validate(model)
.then(() => {
// 课堂作业,找出我的bug修改

// validation passed or without error message
VueEvent.emit("validate", { [k]: [] });
})
.catch(({ errors, fields }) => {
return handleErrors(errors, fields);
});
};
const submit = (e) => {
validate("");
ctx.emit("finish");
};
onMounted(() => {
VueEvent.on("check", (k) => {
validate(k);
});
});
return {
submit,
validated,
};
},

复制代码
定义yue-ma-edu-form-item用于承载输入组件

通过provider跨组件传输数据

provide("name", props.name);

自定义输入组件 yue-ma-edu-input

复制代码
通过 const name = inject("name");获取父级组件传输的数据
监听跨组件事件

VueEvent.on("validate", (res) => {
if (res[name] !== undefined) {
if (res[name].length > 0) {
const error = res[name].pop();
msg.value = error.message;
} else {
msg.value = "";
}
}
});

 

Vue3企业级项目总结

vue3 项目开发 get 到的知识
刚开始用的时候,可怀念 vue2 了,我始终 get 不到 vue3 的精华,也理解不了网上说的组合式API 有多好。vue2 我是轻车熟路,vue3 我是面向文档开发。选择了用 vue3,就要去 get 他的精华,用着用着我发现真香,vue3 和 vite2 结合的项目惊讶到我了。

组合式 API 解决了什么问题?
在开始写项目的时候,我一直没有 get 到组合 API 的有优点,还没有了全局的 this,我就有点不开心了,但是随着项目越来越复杂,页面越来越大的时候我就发现组合 API 真香。特别喜欢。
vue2 数据定义在 data,方法在 method,中间可能还有 watch,computed 等等别的东西,数据定义和方法处理逻辑之间差了十万八千里,当逻辑复杂达到一定长度的时候,追踪一个变量的变化是一件非常头痛的事情,鼠标需要来回滚动。

有了组合 api,这个问题就解决了。所有相关的都可以写在一块。真好,它带来了一种全新的开发方式。如果你是 React 开发用户或者熟悉 React,那么 vue3 上手很快,你甚至都可以在页面中使用 hooks 的方式开发。由于这个项目使用场景比较小,所以在项目中并没有进行采用 hooks 的方式,后续有需要的时候可以考虑使用。了解更多关于组合式 API 请参考文档什么是组合式 API?