vue开发中15个新人常遇见的问题总结记录,为新人点亮一盏灯

346 阅读2分钟

这是我参与8月更文挑战的第4天,活动详情查看:8月更文挑战

这是我前一两年在开发中遇到问题后记录过的问题,后面经验丰富后遇见的问题便少了,就没有记录了,所以暂时只记录了这些问题,后面我遇到问题会往帖子里更新,希望对刚接触前端开发的你们有帮助

vue2打包后显示空白解决

解决方法:

修改一下 config 下面的 index.js 中 bulid 模块导出的路径

module.exports = {
  build: {
    index: path.resolve(__dirname, '../dist/index.html'),
    assetsRoot: path.resolve(__dirname, '../dist'),
    assetsSubDirectory: 'static',
    assetsPublicPath: './',
    productionSourceMap: true,
    devtool: '#source-map',
    productionGzip: false,
    productionGzipExtensions: ['js''css'],
    bundleAnalyzerReport: process.env.npm_config_report
  }
 }

assetsPublicPath 默认的是 ‘/’ 也就是根目录。而我们的 index.html 和 static 在同一级目录下面。 所以要改为 ‘./ ’;

再次执行 npm run build

vue+element打包后样式混乱

解决方法:

原因是main.js中import顺序导致自己写的样式被覆盖

import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
import App from './App'
import Vue from 'vue'
import router from './router'

调整下顺序即可

vue2中element小图标不显示

解决方法:

修改 biuld 下的 utils.js,ctrl+f 搜索 ExtractTextPlugin.extract,修改此代码块

return ExtractTextPlugin.extract({
  use: loaders,
  fallback'vue-style-loader',
  publicPath'../../'
})

url传参变化或者刷新浏览器,页面无变化问题

解决方法:

添加监听事件

watch: {
 '$route' (to, from) { //监听路由是否变化
  if(to.params){// 判断条件1 判断传递值的变化
   //获取数据
   this.xxx(); 监听地址栏传参数发生变化时执行方法
   console.log(to,this.$route.query)
    }
 }
} 

监听重新获取数据或者使用forceUpdate方法

this.$forceUpdate();

更换url前进后退无效

解决方法:

1.路由里直接设置history模式

2.hash 模式用 onhashchange 事件

mounted () {
 // 检测浏览器路由改变页面不刷新问题,hash模式的工作原理是hashchange事件
 window.addEventListener('hashchange'() => {
  let currentPath = window.location.hash.slice(1)
  if (this.$route.path !== currentPath) {
   this.$router.push(currentPath)
  }
 }, false)
}

解决跨域

修改一下config下面的index.js中dev模块

const test = "http://xxx.xx.xx.xx:xxxx"//apiurl

module.exports = {
dev: {
    // Paths
    assetsSubDirectory: 'static',
    assetsPublicPath: '/',
    proxyTable: {
       '/api': {
         target: test,
         changeOrigin: true,
         pathRewrite: {
           '^/api''/api'
         }
       }
    }

不加这段代码访问为localhost:8080/api/login,加入后会重定向到xxx.xx.xx.xx:xxxx/api/login,若…

路由跳转不在顶端

方法一

export default new Router({
//加入下列代码
  scrollBehavior(to,from,saveTop){
    if(saveTop){
      return saveTop;
    }else{
      return {x:0,y:0}
    }
  }

更新:vue-router已不再支持此方法,更换以下:

  1. 页面指定了DTD,即指定了DOCTYPE时,使用document.documentElement。

  2. 页面没有DTD,即没指定DOCTYPE时,使用document.body。

router.afterEach((to, from) => {
  let bodySrcollTop = document.body.scrollTop
  if (bodySrcollTop !== 0) {
    document.body.scrollTop = 0
    return
  }
  let docSrcollTop = document.documentElement.scrollTop
  if (docSrcollTop !== 0) {
    document.documentElement.scrollTop = 0
  }
})

方法二

main.js

router.beforeEach((to, from, next) => {    
    // chrome
    document.body.scrollTop = 0
    // firefox
    document.documentElement.scrollTop = 0
    // safari
    window.pageYOffset = 0
    next()
})
//每次点击分页的时候,页面也会停留在之前浏览的位置,在调完接口后也加入下面几行代码就好了。
// chromedocument.body.scrollTop = 0
// firefoxdocument.documentElement.scrollTop = 0
// safariwindow.pageYOffset = 0

判断用移动端和浏览器,使用不同的样式

var sUserAgent = navigator.userAgent.toLowerCase();
var bIsIpad = sUserAgent.match(/ipad/i) == "ipad";
var bIsIphoneOs = sUserAgent.match(/iphone os/i) == "iphone os";
var bIsIphone = sUserAgent.match(/iphone/i) == "iphone";
var bIsMidp = sUserAgent.match(/midp/i) == "midp";
var bIsUc7 = sUserAgent.match(/rv:1.2.3.4/i) == "rv:1.2.3.4";
var bIsUc = sUserAgent.match(/ucweb/i) == "ucweb";
var bIsAndroid = sUserAgent.match(/android/i) == "android";
var bIsCE = sUserAgent.match(/windows ce/i) == "windows ce";
var bIsWM = sUserAgent.match(/windows mobile/i) == "windows mobile";
if (
bIsIpad ||
bIsIphoneOs ||
bIsIphone ||
bIsMidp ||
bIsUc7 ||
bIsUc ||
bIsAndroid ||
bIsCE ||
bIsWM
) {
 console.log('h5');
 require("./assets/style/h5.less");
 this.$store.dispatch("ish5");
} else {
 console.log('web');
 require("./assets/style/web.less");
 this.$store.dispatch("isweb");
}

平滑定位到锚点

首先添加d_jump的class作为锚点

<div class="holidayList scroll_content">
 <ul>
  <li v-for="(v,i) in imgList" :key="i.id" :id="'loc'+i" class="d_jump">
   <img class="imgLogo" :src="v.logo" alt>
  </li>
 </ul>
</div>

然后定义操作锚点的方法jump(index)

<ul>
 <li @click="jump(0)">xxx1</li>
 <li @click="jump(1)">xxx2</li>
 <li @click="jump(2)">xxx3</li>
 <li @click="jump(3)">xxx4</li>
</ul>

method:

jump(index) {
    // 用 class="d_jump" 添加锚点
    let jump = document.querySelectorAll(".d_jump");
    let total = jump[index].offsetTop;
    let distance =
        document.documentElement.scrollTop || document.body.scrollTop;
    // 平滑滚动,时长500ms,每10ms一跳,共50跳
    let step = total / 50;
    if (total > distance) {
        smoothDown();
    } else {
        let newTotal = distance - total;
        step = newTotal / 50;
        smoothUp();
    }

    function smoothDown() {
        if (distance < total) {
            distance += step;
            document.body.scrollTop = distance;
            document.documentElement.scrollTop = distance;
            setTimeout(smoothDown, 10);
        } else {
            document.body.scrollTop = total;
            document.documentElement.scrollTop = total;
        }
    }

    function smoothUp() {
        if (distance > total) {
            distance -= step;
            document.body.scrollTop = distance;
            document.documentElement.scrollTop = distance;
            setTimeout(smoothUp, 10);
        } else {
            document.body.scrollTop = total;
            document.documentElement.scrollTop = total;
        }
    }
}

vue2中刷新浏览器丢失vuex里store信息

APP.vue里监听的所有页面的刷新, 直接加入以下代码

//刷新前存储store
created() {
    if (sessionStorage.getItem("store")) { //页面加载前读取sessionStorage里的状态信息
        this.$store.replaceState(Object.assign({}, this.$store.stateJSON.parse(sessionStorage.getItem("store"))))
    }
    window.addEventListener("beforeunload"() => { //在页面刷新前将vuex里的信息保存到sessionStorage里
        sessionStorage.setItem("store"JSON.stringify(this.$store.state))
    })
}

重复点击路由报错

/router/index中添加以下代码

import Vue from 'vue'
import Router from 'vue-router'

const routerPush = Router.prototype.push
Router.prototype.push = function push(location) {
    return routerPush.call(this, location).catch(error => error)
}

返回加密前参数

function objKeySort(arys, isEncodeURI) {
    isEncodeURI = isEncodeURI == undefined ? true : isEncodeURI;
    let newkey = Object.keys(arys).sort();
    let parStr = "";
    for (var i = 0; i < newkey.length; i++) {
        if (isEncodeURI) {
            parStr += newkey[i] + "=" + encodeURIComponent(arys[newkey[i]]) + "&";
        } else {
            parStr += newkey[i] + "=" + arys[newkey[i]] + "&";
        }
    }
    return parStr == "" ? "" : parStr = parStr.substr(0, parStr.length - 1); //返回排好序的新参数
}

获取后台二进制流图片

后台接口返回来二进制流图片格式,network上是图片,但是打印出来会是类似于乱码的东西,其实是二进制流格式,这时候就需要转换成base64 这里是vue+axios

//获取验证码
getChkcode() {
  // 调用接口
    this.$axios.get('/api/chkcode.aspx', {
            responseType'arraybuffer'
        })
        .then(response => { //这里的第一次处理后台返回来的二进制留数据 转化为base64 
            return 'data:image/png;base64,' + btoa(
                new Uint8Array(response.data).reduce((data, key) => data + String.fromCharCode(key), '')
            )
        })
        .then(res => { //这一次箭头函数是依赖于第一次.then函数处理的data值
            console.log(res) //这时候打印出来就是base64地址了,直接赋值给:src即可
        }, (error) => {
            console.log(error)
        })
}

vue-photo-preview全屏无效

异步获取数据后需要在后面加一行代码刷新重置一下

this.$previewRefresh();

常见报错解决

出现以下情况时

compilation. templatesPlugin is not a function


TypeError: Cannot destructure property createHash of 'undefined' or 'null'

  1. 安装最新webpack4以上
npm add webpack@latest
  1. 删除node_modules,重新安装,推荐使用下面的命令
npm install rimraf -g
rimraf node_modules
npm i

vue-loader was used without the corresponding plugin. Make sure to include

重新安装vue_loader

npm i --save-dev vue-loader

Module build failed: Error: Cannot find module 'file-loader'

重新安装vue_loader

npm i --save-dev file-loader