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作为初始化页面,如果找不到,就往下一级目录找.**

备注:如果后端接口都配置了,还是返回这个,要情况下浏览器缓存,可以在开发者模式看到这个响应from disk cache

 

posted @ 2019-05-15 18:11  番茄土豆西红柿  阅读(363)  评论(0编辑  收藏  举报
TOP