PS:Vue
使用之前,可不用了解原理,亦不用了解本项目架构的搭建(后续学习中可以了解),官网教程认真看一遍,边做边学;Vue全家桶(Vue + Vue Router + Vuex)认真了解下。未对JavaScript
有所了解,不建议直接学习并使用Vue框架或其他前端框架。
如果项目中的代码编写与学习时不相同,是因为使用了ES7中的修饰器,引入了依赖vue-class-component
,请阅读README文件(本文件)的第十条。
项目中遇到的问题及问题解决方法,请记录在doc文件夹下的相关文件里(写在本文件下面亦可),形成问题解决库很重要。
介绍项目整体原则以及项目启动流程
项目中各个模块的原则以及可能引申涉及出来的问题
项目中遇到的有关Vue的问题
项目中遇到的有关router的问题
项目中遇到的有关git的问题
项目中遇到的有关mock的问题
npm install
npm run serve
npm run build
npm run dev-build
npm run lint
npm install node-sass --sass-binary-site=http://npm.taobao.org/mirrors/node-sass
https://github.com/cmp-cc/vue-cookies
NavigationDuplicated {_name: "NavigationDuplicated", name: "NavigationDuplicated"}
在引用vue-router的文件中添加一段代码
const originalPush = Router.prototype.push;
Router.prototype.push = function push(location) {
return originalPush.call(this, location).catch(err => err);
};
注:Element UI ^2.13.0版本已修复此bug
<el-dialog
v-if="dialogFormVisible"
title="新增图标"
width="45%"
:visible.sync="dialogFormVisible"
:append-to-body="true"
:close-on-click-modal="false"
:close-on-press-escape="false"
:show-close="false"
center
>
:visible.sync 与 v-if同时使用
preload
和资源预读取 prefetch
针对于Vue-cli 3
webpack打包之后的文件,在首次访问时,会对资源进行预读取,如不想进行预读取可进行如下操作:
在webpack配置文件中,移除 prefetch
插件(和具体项目框架搭建有所差异):
chainWebpack: (config) => {
// 移除 prefetch 插件
config.plugins.delete('prefetch');
},
发版过程中存在很多的发版环境,例如测试环境、开发环境等,我们需要根据不同的环境做相应的调整。
vue-cli-service build --mode test
会在 test 模式下加载可能存在的 .env、.env.test 和 .env.test.local 文件然后构建出生产环境应用。
env.test
```
NODE_ENV=production
VUE_APP_API_BASE_URL=http://47.99.189.168:8090/
```
增加变量 test
以 VUE_APP_
开头的变量会被 webpack.DefinePlugin
静态嵌入到客户端侧的包中
VUE_APP_SERVER_MODE=test vue-cli-service build --modern --mode production
以本项目为例:
.env.test 为本地开发环境
NODE_ENV = 'development'
VUE_APP_ENV = 'test'
.env.development 为测试环境
NODE_ENV = 'production'
VUE_APP_ENV = 'development'
.env.production 为正式环境(线上环境)
NODE_ENV = 'production'
VUE_APP_ENV = 'production'
package.json 文件
"scripts": {
"serve": "vue-cli-service serve --mode Member",
"build": "vue-cli-service build --mode production",
"dev-build": "vue-cli-service build --mode development",
"lint": "vue-cli-service lint"
},
说明:
测试环境 NODE_ENV = 'production'
,是因为webpack在打包时,会对文件进行压缩;如果 NODE_ENV = 'development'
时,在打包时不会对文件进行压缩,导致文件体积会特别大。
在处理列表时,常常有删除一条数据或者新增数据之后需要重新刷新当前页面的需求。
用vue-router重新路由到当前页面,页面是不进行刷新的
采用window.reload()
,或者router.go(0)
刷新时,整个浏览器进行了重新加载,闪烁,体验不好
provide / inject
组合
作用:允许一个祖先组件向其所有子孙后代注入一个依赖,不论组件层次有多深,并在起上下游关系成立的时间里始终生效。
<template>
<el-container>
<el-main>
<router-view v-if="isRouterAlive" />
</el-main>
</el-container>
</template>
<script>
import Vue from 'vue';
import Component from 'vue-class-component';
@Component({
provide() {
return {
reload: this.reload,
};
},
})
export default class Main extends Vue {
isRouterAlive = true;
reload() {
this.isRouterAlive = false;
this.$nextTick(() => {
this.isRouterAlive = true;
});
}
}
在使用reload
的页面:
import Vue from 'vue';
import Component from 'vue-class-component';
@Component({
inject: ['reload'],
})
export default class Child extends Vue {
handleSwitchOrg() {
this.reload();
}
}
</script>
使用状态管理机Vuex,用户退出登录时,Vuex的存储数据未清理,导致数据重复
js
[ACCOUNT_LOGOUT]({ commit }, payload) {
return accountApi.accountLogout(payload.id).then((res) => {
commit(SET_USERINFO, {});
return res;
});
},
Vuex文档对数据进行加锁处理(详见account下的components里的pageAside.vue文件)
// 获取菜单数据,格式化数据,加锁以防多次重复调用,产生错误
getRulesData() {
if (this.flag) {
this.flag = false;
// ......
this.flag = true;
}
}
规则不允许一元运算符++和--。
错误示例:
var foo = 0;
foo++;
var bar = 42;
bar--;
for (let i = 0; i < l; i++) {
return;
}
正确示例:
var foo = 0;
foo += 1;
var bar = 42;
bar -= 1;
for (i = 0; i < l; i += 1) {
return;
}
for ... in
循环遍历对象for in
将包含通过原型链继承的属性。此行为可能会导致 for 循环中出现意外的项目。
for (key in foo) {
doSomething(key);
}
请注意,foo.hasOwnProperty(key)
在某些情况下,简单检查可能会导致错误; 见 no-prototype-builtins
。
规则细节
此规则旨在防止使用for in
循环而不过滤循环中的结果时可能出现的意外行为。因此,当for in
循环不会用if语句过滤结果时,它会发出警告。
此规则的错误代码示例:
/*eslint guard-for-in: "error"*/
for (key in foo) {
doSomething(key);
}
此规则的正确代码示例:
/*eslint guard-for-in: "error"*/
for (key in foo) {
if (Object.prototype.hasOwnProperty.call(foo, key)) {
doSomething(key);
}
if ({}.hasOwnProperty.call(foo, key)) {
doSomething(key);
}
}
el-image
组件造成页面无法滚动a 标签里有 el-image
组件进行链接跳转时,会为body
添加内联属性:overflow:hidden
,由此造成页面无法进行滚动。
<router-link :to="{ name: 'journal.add'}">
<el-image
style="width: 50px; height: 50px"
src="https://nuodastorage.oss-cn-beijing.aliyuncs.com/gyhq/0/common/png/2019/10/30/15724335243123882.png"
/>
</router-link>
不采用el-image
,使用原生img
<router-link :to="{ name: 'journal.add'}">
<img
style="width: 50px; height: 50px"
src="https://nuodastorage.oss-cn-beijing.aliyuncs.com/gyhq/0/common/png/2019/10/30/15724335243123882.png"
>
</router-link>
尚未知
在此之前,先提一下这个依赖 vue-class-component
是尤大大推出的Vue对typescript支持的装饰器(库)
vue-class-component
强调了几点用法:
1、methods
可以直接声明为类成员方法
2、computed
可以将计算的属性声明为类属性getter / setter:
3、data
数据可以声明为类属性
4、data
、render
和所有Vue生命周期挂钩也可以直接声明为类成员方法,但不能在实例本身上调用它们。在声明自定义方法时,应避免使用这些保留名称。
TypeScript 语法:
import Vue from 'vue';
import Component from 'vue-class-component';
@Component({
props: {
firstName: String,
lastName: String
},
components: {
'component-a': ComponentA
}
})
export class XXXX extends Vue {
firstName: string; // TypeScript 语法
lastName: string;
//初始data
middleName = 'middle';
//computed 属性
get fullName() {
return this.firstName + this.lastName;
}
//method
hello() {
alert(`Hello ${this.fullName}!`);
}
//钩子
mounted() {
this.hello();
}
}
// XXXX 类名,最好以文件名命名
import Vue from 'vue';
import Component from 'vue-class-component';
@Component({
props: {
firstName,
lastName
},
components: {
ComponentA
}
})
export class XXXX extends Vue {
//初始data
middleName = 'middle';
//computed 属性
get fullName() {
return this.firstName + this.lastName;
}
//method
hello() {
alert(`Hello ${this.fullName}!`);
}
//钩子
mounted() {
this.hello();
}
}