架构方面
数据管理
使用vuex,按页面来管理数据,每个页面目录下提供一个store.js文件。
store/index.js中通过require.context()来聚合所有页面目录下的store.js文件,创建为一个个的vuex数据模块。
尝试为每一个state,自动创建一个up开头,首字母大写的mutation。
为每个模块创建一个方便使用的mixin,方便组件使用。computed包含模块的state和getters,methods包含模块的mutations和actions。
import { createNamespaceHelpers as cnh } from 'vuex';
function getKeys(obj) {
if (!obj) obj = Object.create(null);
return Object.keys(obj);
}
function createStoreMixin(module, moduleName) {
const { state, mutations, getters, actions } = module;
const { mapState, mapMutations, mapGetters, mapActions } = cnh(moduleName);
return {
computed: {
...mapState(getKeys(state)),
...mapGetters(getKeys(getters))
},
methods: {
...mapMutations(getKeys(mutations)),
...mapActions(getKeys())
}
};
}
将所有数据模块的mixin放入StoreMixin这个对象,并设置为全局(无需导入即可使用,通过ProvidePlugin)。
// vue.config.js
configureWebpack: {
plugins: [
new webpack.ProvidePlugin({
StoreMixin: [path.resolve(__dirname, 'src/store'), 'StoreMixin']
});
]
}
// .eslintrc.js
globals: {
StoreMixin: true
}
请求发送
接口配置化,按后端微服务组织划分。
读取配置,自动构建请求。
根据环境(app/web),构建请求路径,选择请求器。
提供默认的请求报文解析。
使用vuex发送请求和管理响应数据
// store/index.js
export const $api = (api, postData, options) => {
return store.dispatch('$api', { api, postData, options });
};
Vue.prototype.$api = $api;
数据mock
将app中的访问的数据,自动发送到开发端,并保存为mock文件。
接口请求时,可以指定返回mock文件数据。
// vue.config.js
devServer: {
watchOptions: {
ignored: [/mocks/]
},
before(app) {
app.use(bodyParser.json());
// 将接口数据保存到mock文件
app.post(`/mock/save`, function(req, res) {
// fs.mkdirSync(, { recursive: true }) // 递归创建目录
// fs.writeFileSync()
res.send('ok');
});
// 读取mock文件内容返回
app.post(`/mock/file`, function(req, res) {
// fs.readFileSync(, 'utf8')
res.send(fileContent)
});
}
}
服务组件封装、提升使用的便捷性
- 提供fresourse的助手方法。
viewWillAppear等服务组件方法作为组件的option使用。
function install(Vue) {
const strats = Vue.config.optionMergeStrategies;
strats.viewWillAppear = strats.created;
Vue.mixin({
created() {
const fns = this.$options.viewWillAppear;
if (fns) {
viewWillAppear.set(() => {
fns.forEach(fn => {
try {
fn.call(this);
} catch (e) {}
});
});
}
}
});
}
3.物理栈路由参数混入$route.query中
UI组件封装、二次封装
-
Layout 转化
default插槽作为content插槽,自动获取路由配置的title设置为页面标题,提供默认的返回方法并设置物理返回键。 -
封装Swiper组件,支持动态数据和2种使用方式。
-
封装选卡组件,提供
triggerslot项。 -
alert、dialog便捷使用。
埋点封装
按页面拆分管理埋点事件,在每个页面目录下定义一个events.js文件。
events.js中按事件类型管理事件。
每个事件为一个方法,方法中处理埋点逻辑,并返回埋点业务参数。
在埋点事件方法中处理埋点逻辑的好处,可以从业务代码中剥离开。
提供页面级别的钩子设置页面通用埋点业务参数。
最终合并参数,构建埋点请求并发送。
埋点事件的方法自动绑定调用环境的this。
代码管理
写README
先写README,再开发。
README中写业务需求、思考、测试啥都行,按着README写代码。
将数据处理放在顶层,就是store中。
组件的职责:view + controller
store(vuex)的职责:model
数据的存储、请求、处理都集中在store中。
好处
- 子组件或下游的组件无需处理,防止了重复处理数据的情况
- 由于所有的数据处理都集中在一块(store中),无需重复引入帮助函数等。
- 集中在一块,还可以方便修改与添加。
知识点
Array.prototype.splice
const arr = [1, 2, 3];
const idx = arr.indexOf(4);
arr.splice(idx, 1);
console.log(arr); // [1, 2]
一点要先判断idx > -1。
idx > -1 && arr.splice(idx, 1);
window.onscroll
给window添加onscroll事件,事件处理器参数event的target属性为document。
document的onscroll事件的event.target也是document。
想要获取window的滚动高度,需要使用document.documentElement.scrollTop。