踩坑小结3

1.路由传参undefined?

上一节已经区分过两种传参方式,仍然在踩坑路上越走越远

1
2
let routeData = this.$router.resolve({ name: 'xxx', params: { id: id }})
window.open(routeData.href, '_blank') //新开页面无法获取到id
1
this.$router.push({name:'xxx',params:{id:id}}) //直接替换当前路由可获取到

问了师姐,她说是要用watch监听路由变化,监听出来就是第一种的from.path为根路由,并非是我跳转前的真实当前路由;第二种直接跳转的一切正常。暂时没想到既要新开页面,也希望用name和params传参的办法,先留个坑,之后再填。
不过用path和query传参虽然会显得URL比较丑,但能确保用户刷新后还有数据。

2.v-bind绑定变量与字符串组合

1
2
3
4
5
6
7
8
9
//xx为变量

第一种
:title="`字符串${xx}`"
<div :uid="props.row.id + 'one'"></div>

第二种
:title="'字符串' + xx"
<div :uid="`${props.row.id}two`"></div>

3.父子组件通信传值

父组件A从后端获取数据传给子组件B,子组件B使用父组件A传递过来的值C发起XHR请求数据,再将请求回来的数据用于渲染DOM,但是在发起请求时参数C值是undefined,说明没获取到父组件传递过来的值,在生命周期钩子created,mounted里都没有,但在开发时,若修改了别的地方保存时没有刷新这个值C便又有了,感到很疑惑,因为跟C同时获取回来的其他数据在父组件A中都可以直接使用,甚至不传给子组件,就在原父组件中使用C获取远程数据还是不行,感觉是因为需要使用C的请求异步触发的方法在C有值前就发起了,导致一个undefined。于是想到用watch监听C,逻辑上还是存在这个问题,但是功能实现了,子组件watch到C值后再发起一个请求。

4.导出xlxs数据出错

起初将从后台获取下载数据、转换格式和导出分为三部分。
每次下载数据从后台获取,数据较多需要较长时间,结果就导致数据还没取到就进行转换了,于是报错。

1
Cannot convert undefined or null to object

打印一下const data = this.formatJson(filterVal, response.data) 的data是有值的,数据格式也正确,但是发现先触发了export_json_to_excel(),而其参数data在被触发时还是空的,JS有时候这种异步真的让人崩溃。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
getdata(){
let url = '/api/getdata?id=1234'
this.$axios.get(url).then(response => {
this.downloadData=response.data
})
}

exportExcel() {
import('../vendor/Export2Excel').then(excel => {
const tHeader = ['id', 'name', 'phone-number', 'age'];
const filterVal = ['id', 'name', 'phonenumber', 'age'];
this.getedata();
const data = this.formatJson(filterVal, this.downloadData);
excel.export_json_to_excel({
header: tHeader,
data,
filename: 'Results'
})
})
})
}

formatJson(filterVal, jsonData) {
return jsonData.map(v => filterVal.map(j => v[j]));
}

那么为了确保axios完成后再转换,只得将其写到其中。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
exportExcel() {
var url = '/api/getdata?id=1234'
this.$axios.get(url).then(response => {
import('../vendor/Export2Excel').then(excel => {

const tHeader = ['id', 'name', 'phone-number', 'age'];

const filterVal = ['id', 'name', 'phonenumber', 'age'];


const data = this.formatJson(filterVal, response.data)

excel.export_json_to_excel({
header: tHeader,
data,
filename: 'Results'
})
})
})
}

formatJson(filterVal, jsonData) {
return jsonData.map(v => filterVal.map(j => v[j]));
}

5.上传文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
upload(event) {
if (this.inputFile) {
event.preventDefault();
let data = new FormData(); //new FormData()很重要
data.append("input_file", this.inputFile)
//此处"input_file"要与后端定义的name相同
//不可写成 let data.input_file = this.inputFile
let headers = { headers: { "Content-Type": "multipart/form-data" } }
this.$axios.post("/api/upload", data, headers).then(response => {
...
})
}else if (!this.inputFile) {
this.$message.error('Please Select a file...')
}
},

同时要注意后端对上传文件格式做了过滤。

6.打包拆分JS,引入CDN

一开始打包完有仅app.js都有3.几M,实在太大了,因为是中途改了需求,期初又用了bootstrap的静态模板,这点真的让人炸毛,随之带来的库(如jq)真的太大了,带宽就100KB/S,每次打开网页都需要至少半分钟,影响体验。

第一次考虑切分代码,尽管已经用了官方推荐的webpack路由懒加载方式,考虑到某些库只用在个别组件,便不在main.js中import,东删西删,连大部分注释都去掉了,也没有减少多少。感到绝望!

三种懒加载方式

  • vue异步组件
  • es提案的import()
  • webpack的require.ensure() (推荐)

既然懒加载效果也不明显,那就进入正题!先用 npm run build –report 查看各js占比。看了下占得较多的几个库,其中就有vue和elementUI,OK fine,把它们移出去,第一次打包上线ElementUI is not defined。

报错在这里 module.exports = ElementUI;

原来不小心引入CDN时顺序错了,Vue要在ElementUI前引入,改了后以为这下总没问题了吧,结果还是找不到ElementUI,查了查说是

因为elementUI外部库对外暴露的全局变量是’ELEMENT’,引入其他外部库也是这样,必须填写外部库对外暴露的全局变量名。

遇到一个问题,把整个ElementUI移出去了,但是想要使用其非中文的语言包,比如英语,只知道npm方式下如何在全局修改,如果同样要把locale 移除,在external中要怎么写?

7.vue-cli3静态资源加载404

到最后打包完上线了,静态资源全部404,由于之前用vue-cli2所以每次改一下
config>index.js>build:{… assetsPublicPath: ‘./‘, …}

现在vue-cli3的文件结构有多区别,需要自行配置,根目录新建文件 vue.config.js

1
2
3
module.exports = {
publicPath: "./"
}