18-***********vue开发问题解决积累*******
1.Do not use built-in or reserved HTML elements as component id: table【和关键字冲突】
背景:使用element-ui的table组件,定义文件名为table.vue,然后在一个组件中使用这个组件,使用方法如下
<template> <div> <table></table> </div> </template> <script> import table from './table.vue' export default { components: { table } } </script> <style> </style>
控制台报错如下
[Vue warn]: Do not use built-in or reserved HTML elements as component id: table
原因:组件名不能和html标签重复,所以把table修改为AlterTable即可,注意alter-table也是不可以的
扩展:
由于在模板需要插入到 DOM 中,所以模板中的标签名必须能够被 DOM 正确地解析。主要有三种情况:
一是完全不合法的标签名,例如 </>;
二是与 HTML 元素重名会产生不确定的行为,例如使用 input 做组件名不会解析到自定义组件,使用 button 在 Chrome 上正常但在 IE 上不正常;
三是与 Vue 保留的 slot、partial、component 重名,因为会优先以本身的意义解析,从而产生非预期的结果。
2.vue如何在一个组件中引用另外一个组件并使用
方法一:代码如下
<template> <div> <!-- 3.在template中就可以直接使用了 --> <testComponent></testComponent> </div> </template> <script> //1.先使用import导入你要在该组件中使用的子组件 import testComponent from './testComponent.vue' export default { //2.然后,在components中写入子组件 components: {testComponent}, methods: {}, } </script> <style></style>
方法二:代码如下
template> <div> <!-- 2.在template中使用 --> <testComponent></testComponent> </div> </template> <script> export default { //1.直接在components中写入子组件 components: { testComponent:require('./testComponent.vue').default }, methods: {}, } </script> <style></style>
两者间的区别:初学者暂时没发现啥显著的区别,第一种应该是使用的es6的引入机制,第二种使用的es5的机制.所以,推荐还是使用第一种好点,欢迎知道的同学补充下两者之间具体区别,感激不尽
3.Vue的组件为什么要export default
参考:https://www.cnblogs.com/blog-cxj2017522/p/8562536.html
Vue 是通过 webpack 实现的模块化,因此可以使用 import 来引入模块,例如:
此外,你还可以在 bulid/webpack.base.conf.js 文件中修改相关配置:
意思是,你的模块可以省略 ".js",".vue",“.json” 后缀,weebpack 会在之后自动添加上;可以用 "@" 符号代替 "src" 字符串等。
export 用来导出模块,Vue 的单文件组件通常需要导出一个对象,这个对象是 Vue 实例的选项对象,以便于在其它地方可以使用 import 引入。而 new Vue() 相当于一个构造函数,在入口文件 main.js 构造根组件的同时,如果根组件还包含其它子组件,那么 Vue 会通过引入的选项对象构造其对应的 Vue 实例,最终形成一棵组件树。
export 和export default 的区别在于:export 可以导出多个命名模块,例如:
//demo1.js export const str = 'hello world' export function f(a){ return a+1 }
对应的引入方式:
//demo2.js import { str, f } from 'demo1'
export default 只能导出一个默认模块,这个模块可以匿名,例如:
//demo1.js export default { a: 'hello', b: 'world' }
对应的引入方式:
//demo2.js import obj from 'demo1'
引入的时候可以给这个模块取任意名字,例如 "obj",且不需要用大括号括起来。
4.vue在echart中调用事件 给data里的数据赋值 用watch监听不到变化?【this指向问题】
参考:https://segmentfault.com/q/1010000017108282
问题描述
在vue中调用echart中的timelinechanged事件,并将里面的currentIndex赋给data中的变量,随后用watch监听这个变量的变化,发现监听不到
问题出现的环境背景及自己尝试过哪些方法
相关代码
mounted() {
this.myChart = echarts.init(this.$refs.chartStock);
this.myChart.on("timelinechanged", function(params) {
this.currentIndex = params.currentIndex;
console.log(this.currentIndex);
});
}
watch: {
currentIndex: function() {
console.log("hi");
}
}
你期待的结果是什么?实际看到的错误信息又是什么?
在watch中可以监听到currentIndex的变化,但是并没有监听到
解决方法:
this
绑定问题,你可以试着在在timelinechanged
的回调函数中输出 this ,应该是 undefined
。正确方法应该是使用箭头函数,要不就在用个难看的 that 代替 this。
this.myChart.on('timelinechanged', (params) => { this.currentIndex = params.currentIndex console.log(this.currentIndex) })
5.vue首次赋值不触发watch(deep immediate handler)
参考:https://www.cnblogs.com/leeke98/p/9373455.html
watch:{ "aaa":{ immediate:true, handler:function(){ } }
可通过其immediate 属性进行配置,默认为false
6.浏览器console报错:Uncaught (in promise) error
解决方法:VUE 调接口的某个方法没有加上 catch 而已。加上应该就不会报了。
fetchOverview(this.listQuery).then(response => { console.log('1111111111111111111') }).catch(error => { console.log(error); })
参考: https://segmentfault.com/q/1010000015884264?utm_source=tag-newest
7.vue用request.js封装了axios,现在遇到的问题是通过request请求后端接口,获取不到response,catch打印的总是error
代码如下
mounted() { this.initChart(); }, methods: { initChart() { this.chart = echarts.init(document.getElementById(this.id)); fetchOverview().then(response => { console.log(response) // 这个无法打印 console.log(2222) }).catch(error => { console.log(error); // 会打印error }) .... }, }
问题原因:request.js对axios做了封装,同时对请求的发出和返回都做了拦截处理,如下request的代码
// request interceptor service.interceptors.request.use( config => { // do something before request is sent if (store.getters.token) { // let each request carry token // ['X-Token'] is a custom headers key // please modify it according to the actual situation config.headers['X-Token'] = getToken() } return config }, error => { // do something with request error console.log(error) // for debug return Promise.reject(error) } ) // response interceptor service.interceptors.response.use( /** * If you want to get http information such as headers or status * Please return response => response */ /** * Determine the request status by custom code * Here is just an example * You can also judge the status by HTTP Status Code */ response => {const res = response.data // if the custom code is not 20000, it is judged as an error. if (res.code !== 20000) { Message({ message: res.message || 'error', type: 'error', duration: 5 * 1000 }) // 50008: Illegal token; 50012: Other clients logged in; 50014: Token expired; if (res.code === 50008 || res.code === 50012 || res.code === 50014) { // to re-login MessageBox.confirm('You have been logged out, you can cancel to stay on this page, or log in again', 'Confirm logout', { confirmButtonText: 'Re-Login', cancelButtonText: 'Cancel', type: 'warning' }).then(() => { store.dispatch('user/resetToken').then(() => { location.reload() }) }) } return Promise.reject(res.message || 'error') } else { return res } }, error => { console.log('err' + error) // for debug Message({ message: error.message, type: 'error', duration: 5 * 1000 }) return Promise.reject(error) } )
所以需要在后端的API返回中添加code:20000,然后才可以打印出response来。
8.使用vue的v-if判断数组长度length报错解决方案
v-if="form.details.length>0"
项目中使用v-if判断数组长度报错:Error in render: "TypeError: Cannot read property 'length' of undefined"
解决方法:
v-if="form.details.attrs !== undefined && form.details.attrs.length >0"
完美解决!
9.vue上线如何debug
本地开发环境可以使用console.log() ,线上使用console.log()不能知道是哪个文件的那行输出的console,且如果遇到快速死循环的情况下,也是无法看console日志的,
解决办法:在文件需要调试的地方使用alert('输出内容') ,同时在catch的error中也alert(error),示例如下
if (this.isCasCallback()) { // alert('if1---') const sso_token = this.getSsoToken() const sso_email = this.getSsoEmail() const sso_group = this.getSsoGroup() const sso_time = this.getSsoTime() const sso_username = this.getSsoUsername() const secretKey = mySettings.mySettings.ssoConfig.secretKey var md5_value = md5(sso_email + sso_group + sso_time + sso_username + secretKey) if (md5_value === sso_token) { // alert('md5 1---') getUserInfo({ 'sso_token': sso_token }).then(res => { if (res.data.code === 200) { // alert('200--') var userinfo = {} userinfo['username'] = res.data.user.username userinfo['realname'] = res.data.user.realname userinfo['email'] = res.data.user.email userinfo['token'] = sso_token // console.log(userinfo) store.dispatch('user/login', userinfo) } else { // alert('not 200') this.toAuth() } }).catch(error => { alert(error) }) } } else { // alert('else1---') this.toAuth() }
10.vue上线提示We're sorry but XXX doesn't work properly without JavaScript enabled
总觉得这句话很眼熟,在哪里见过。。。 我的项目是vue-cli创建的,搜索全局发现 index.html 中有一句一模一样的话。
这就简单了,说明请求返回了index页面啊
为什么会这样呢?
答案非常明显,是server配置不对,没有匹配到要请求的路径。如果是开发阶段(运行npm run serve)检查一下代理devServer.proxy ,如果是在测试环境或者生产环境,检查nginx,或者Apache等server。
举个例子,以nginx配置为例
例如http请求的路径是 /login,首先检查nginx.conf文件中的location,是否配置了/login的转发。如果配置了,检查是否配错了,多个“/”少个”/”都可能导致正则匹配不到
参考我的配置
server{
listen 8081;
server_name localhost;
location ~^/(oauth|login|user|api) {
proxy_http_version 1.1;
proxy_pass http://xxxxxx:8080; # 这是后端接口的地址,http见到oauth开头,login开头等都会跳转到这里
#设置允许跨域
add_header Access-Control-Allow-Origin *;
add_header Access-Control-Allow-Methods "POST, GET, DELETE, OPTIONS";
add_header Access-Control-Allow-Headers "Origin, Authorization, Accept";
add_header Access-Control-Allow-Credentials true;
}
location / {
root /usr/dev/project/fe/test;
# index index.html index.htm;
try_files $uri $uri/ /index.html; #这里是history路由模式,需要加,如果是hash模式不需要。
}
}
复制代码
另外,我看到一些其他网站说是history问题,(因为我项目创建就已经配好了try_files,没有遇到因为history导致报错):
如果vue的路由是history模式,需要在location里面加上这句
location / {
try_files $uri $uri/ /index.html;
}
复制代码
这句话的意思是 从root的路径开始作为起始路径,找到第一个index.html作为初始化页面,如果找不到,就往下一级目录找.**