vue项目经历难点回顾:

1.做一个活动页面的时候,用history模式后上传到服务器之后,如果访问内容页(子页)之后,按f5刷新,会报一个404错误,

    如果是Apache服务器,咱们可以自己做一个文件重新定向到index文件,

    如果是nginx服务器,也是需要重定向配置服务器,然后重启服务器,

  2.线上跨域问题

本地开发

Webpack-dev-server    proxyTable代理

proxyTable{
        api:{
            pathRewrite:{
                
            }
        }
    }
package.json    proxy

线上开发

后端:

    Allow-accces-origin:"*"

前端:   

    nginx配置

    jsonp

 

3.vue项目中用v-for 循环本地图片, 图片不显示,

解决办法:1.使用require动态引入图片,

         2.或将图片放static文件夹里面

4.css引用图片打包后找不到文件资源的问题

css引入图片再打包后,style-loader无法设置自己的publicPath,所以只要改变style-loader中的publicPath即可,一行代码即可以搞定,

找到build/util.js文件中ExtractTextPlugin的css路径,手动添加publicPath参数,

if (options.extract) {
return ExtractTextPlugin.extract({
use: loaders,
publicPath: '../../',
fallback: 'vue-style-loader'
})
} else {
return ['vue-style-loader'].concat(loaders)
}

重新build一次,问题解决了

5.引入rem之后存在个问题,会导致后期引入的ui库样式变小

安装postcss-px2rem-exclude

npm install postcss-px2rem-exclude --save

因为 postcss-plugin-px2rem 这个插件  配置选项上有  exclude 属性,它可以配置 是否对 某个文件夹下的所有css文件不进行从px到rem的转换。

  所以我们可以利用这个特性,把项目中的  node_module 文件夹里面安装的ui框架排除掉。这样如果我们项目中是用了前端UI框架的话,就不会吧UI框(Vant,Element等)中的 px单位转换成rem了

配置exclude选项,需要注意的是这个配置在vue.config.js中式不起作用的,如图。

正确的配置位置是项目根目录下的postcss.config.js文件,如果你的项目没有生成这个独立文件,就需要在你的package.js里设置。

postcss.config.js
module.exports = {
    plugins: {
    autoprefixer: {},
    "postcss-px2rem-exclude": {
    remUnit: 75,
    exclude: /node_modules|folder_name/i
    }
   }
};
 
package.json
"postcss": {
    "plugins": {
    "autoprefixer": {},
    "postcss-px2rem-exclude":{
    "remUnit": 75,
    "exclude":"/node_modules|floder_name/i"
    }
  }
},

 

6.node更新后,报错:

报错:

Module build failed (from ./node_modules/sass-loader/lib/loader.js): Cannot find module 'node-sass‘

 

npm cache clean -force     //npm清除缓存

npm install -g mirror-config-china  //切换国内镜像

npm install node-sass

    

7.从详情页返回列表时保存浏览位置

用到keep-alive来缓存页面

    当详情页中改变列表数据时,配合keep-alive,需要在vue钩子函数activated中,对数据进行更改

    activated keep-alive组件激活时调用。

    deactivated keep-alive组件停用时调用。

1.用到keep-alive来缓存页面

2.当详情页中改变列表数据时,配合keep-alive,需要在vue钩子函数activated中,对数据进行更改

3.在从其他页面进入时,页面要重新加载数据。页面从列表进入其他页面(非详情页)时,销毁当前的vue实例。此时需用到组件内的路由守卫,beforeRouteEnter和beforeRouteLeave

    8.使用flex布局,文字超出部分变省略号

  使用flex布局的时候,子元素使用了flex:1这个属性来占满剩下的宽度,但是超出部分的文字不能变成省略号,而是把元素给撑开了。这是因为如果没有设置width,当内部元素的内容大小超过平均分配的剩余空间时,元素的宽度等于内容大小。所以宽度要设置成0,直接设置width为0可以保证元素宽度平分父元素宽度。  

 

overflow: hidden;/*超出部分隐藏*/

text-overflow:ellipsis;/* 超出部分显示省略号 */

white-space: nowrap;/*规定段落中的文本不进行换行 */

flex:1;

width:0

9.实现权限控制

   在用户登录的时候,后台会返回一个token,我们把token存在本地cookie或者localstorge、sessionstorge中,然后所有的api接口请求都带上这个token,后台拿到token就知道用户身份,也知道用户有哪些权限。用户在退出的时候,删除token。

 

路由全局守卫        router.beforeEach(to,from,next)

当从一个路由跳转到另一个路由时触发此守卫,也叫全局前置守卫。

    所以它是跳转前触发的。任何路由跳转都会触发。

    每个守卫都有三个参数:

             to:这是你要跳去的路由对象;

             from:这是你要离开的路由对象;

             next:是一个方法,它接收参数;

                next()    跳转

                next(flase)  中断跳转

                next({path:"/"}) 中断跳转,跳转到一个新的路径

axios拦截器

使用axios 实现登录功能的流程(拦截器)

  先添加拦截器判断, 利用interceptors 调用request ,判断token 是否存在,如果存在,直接跳转

 

axios拦截器:

// 请求拦截,可以将请求的配置进行二次处理。
axios.interceptors.request.use(config=>{
    // config 是axios的配置信息.
    // console.log(config);
    if(localStorage.token){
        config.headers = {
            authorization:localStorage.token
        }
    }
    store.commit("CHANGE_LOADING",true);
    config.url = "/ele"+config.url;
    return config;
})
 
 
// 响应拦截
axios.interceptors.response.use(({data})=>{
    console.log(44444444);
    // 返回的值即是axios得到的值
    store.commit("CHANGE_LOADING",false);
    if(data.ok === 2 || data.ok === 3){
        store.commit("OUT_LOGIN");
    }else{
        return data;
    }
10.canvas图片问题
做的一个项目需要将两张图片合成一张图片输出,想到可以用canvas来实现图片的合成
var self = this;
var codeImg = document.getElementById("qrcode").getElementsByTagName("img")[0];
var bgImg = document.createElement("img");
codeImg.setAttribute("crossOrigin", 'anonymous');
bgImg.setAttribute("crossOrigin", 'anonymous');
var canvas = document.getElementById("myCanvas");
canvas.width = "375";
canvas.height = '667';
var ctx = canvas.getContext("2d");
ctx.rect(0,0,375,667);
ctx.fillStyle = '#fff';
ctx.fill();

 

问题1:

通过canvas合成图片有一个要注意的技术点,就是获取的img元素,需要设置属性img.setAttribute("crossOrigin","anonymous")

不设置该属性的话,就会出现错误如下:

Failed to execute 'toDataURL' on 'HTMLCanvasElement': Tainted canvases may not be exported.

 

问题2:

在这个图片合成的过程中,有一个问题就是由于有一个图片是需要请求服务器显示的,所以,在用canvas合成的过程中,需要判断服务器已经下载完成显示后,才进行ctx.drawImage(),否则就会出错。这就需要通过onload事件在判断图片是否加载完成

    bgImg.src = self.imgsrc;

    bgImg.addEventListener('load',function() {

    self.isShow = true;

    ctx.drawImage(bgImg,0,0,375,667);

    ctx.drawImage(codeImg,270,568,90,90);

    imgURL = canvas.toDataURL("image/png");

    var img = new Image();

    document.getElementById("imgWrap").appendChild(img);

    img.src = imgURL;

    self.finalSrc = imgURL;

    img.style.width = 100 + '%';

    img.style.height = 100 + '%';

    canvas.style.display = "none";

    })

原因:

用到了 window.onload ,在这个事件发生时初始化,然后在 iOS webview 上这个事件不触发

解决方法:

bgImg.src = self.imgsrc;放在onload事件的后面,

 

 

 

组件封装:

Vue组件封装过程

● 首先,使用Vue.extend()创建一个组件

● 然后,使用Vue.component()方法注册组件

● 接着,如果子组件需要数据,可以在props中接受定义

● 最后,子组件修改好数据之后,想把数据传递给父组件,可以使用emit()方法

1.在公共方法中(如 public.js 中),加入函数防抖和节流方法

// 防抖
export function _debounce(fn, delay) {
    var delay = delay || 200;
    var timer;
    return function () {
        var th = this;
        var args = arguments;
        if (timer) {
            clearTimeout(timer);
        }
        timer = setTimeout(function () {
            timer = null;
            fn.apply(th, args);
        }, delay);
    };
}
// 节流
export function _throttle(fn, interval) {
    var last;
    var timer;
    var interval = interval || 200;
    return function () {
        var th = this;
        var args = arguments;
        var now = +new Date();
        if (last && now - last < interval) {
            clearTimeout(timer);
            timer = setTimeout(function () {
                last = now;
                fn.apply(th, args);
            }, interval);
        } else {
            last = now;
            fn.apply(th, args);
        }
    }
}

2、在需要使用的组件引用

import { _debounce } from "@/utils/public";

3、在 methods 中使用

methods: {
    // 改变场数
    changefield: _debounce(function(_type, index, item) {
        // do something ...
    }, 200)
  }

 

2.封装axios

import axios from 'axios'
// Add a request interceptor
axios.interceptors.request.use(function (config) {
    // Do something before request is sent
    return config;
  }, function (error) {
    // Do something with request error
    return Promise.reject(error);
  });
// Add a response interceptor
axios.interceptors.response.use(function (response) {
    // Do something with response data
    return response;
  }, function (error) {
    // Do something with response error
    return Promise.reject(error);
  });
export default axios