工作中遇到的问题及小知识点

 

一、本地vue项目配置IP地址访问,可以让同局域网内的同事预览


  解决:在package.json文件中 dev中配置 --host 本机IP
  "scripts": {
    "dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js --host 10.10.50.73",
    "start": "npm run dev",
    "build": "node build/build.js"
   },

 

二、Vue使用axios请求数据,默认post请求传参是json格式,但后台需要formData格式

 

  1、 FormData格式

     let newdate = new FormData()
               newdate.append('title', item.file.name);
               newdate.append('tags', 'brand_action_upload');    
               newdate.append('multipartFile', result);

  2、qs解决

  解决:使用node的qs模块 qs是一个npm仓库所管理的包,可通过npm install qs命令进行安装.

  qs.parse()将URL解析成对象的形式  

let url = 'method=query_sql_dataset_data&projectId=85&appToken=7d22e38e-5717-11e7-907b-a6006ad3dba0';
qs.parse(url);
        // {
        //     method:'query_sql_dataset_data',
        //     projectId:85,
        //     appToken:'7d22e38e-5717-11e7-907b-a6006ad3dba0'
        // }

  qs.stringify()将对象 序列化成URL的形式,以&进行拼接

let obj= {
    method: "query_sql_dataset_data",
    projectId: "85",
    appToken: "7d22e38e-5717-11e7-907b-a6006ad3dba0",
    datasetId: " 12564701"
};
qs.stringify(obj);
    //'method=query_sql_dataset_data&projectId=85&appToken=7d22e38e-5717-11e7-907b-a6006ad3dba0'

 

  import axios from 'axios';
  import qs from 'qs';

  this.$axios({
    method: 'post',
    url: url,
    data: qs.stringify(data)
  }).then(res => {})

 

三、过滤器(简单)
  filters: {
    visitedFilters(value) {
      let set = {0: "未到访", 1: "已到访"};
      return set.hasOwnProperty(value) ? set[value] : value
    },
  },

 

四、在H5中使用qrcodejs2生成二维码

  npm i qrcodejs2
  import QRCode from 'qrcodejs2'

  this.$nextTick(() => {
    document.getElementById('qrcode').innerHTML = '';
    this.qrCode = new QRCode('qrcode', {
      width: 200, // 设置宽度,单位像素
      height: 200, // 设置高度,单位像素
      text: this.urlData.urlValue // 设置二维码内容或跳转地址
    });
  })

 

五、深拷贝,浅拷贝问题
  在做el-select 下拉数据过多时,region_code ,region_name 以分页形式显示(显示前15条,之后可进行搜索),但是在数据回显时,发现在15条数据之后,因为没有数据,回显失败,
  进行数据回显时(region_code和region_name互换值),在不进行更改时,保存提交时时(region_code和region_name再转换回来)时发现
  问题:
    当用obj1复制了一个对象obj2, 更改obj1内的属性时,obj2内的会同步更改,
  原因:
    因为 = 复制为浅拷贝,只拷贝了它的栈内存中的"引用路径",所以当更改obj1时,更改了堆内存中的值,obj2的指向也是它,所以会同步修改

  解决:

    运用深拷贝,复制时不仅要拷贝栈内存中的引用路径,堆内存中的值也要同步复制

  方法1:

    首推的方法简单有效,JSON.stringfy()和JSON.parse()即可搞定。但是这种简单粗暴的方法有其局限性。当值为undefined、function、symbol 会在转换过程中被忽略。。。所以,对象值有这三种的话用这种方法会导致属性丢失。
    var person = {
      name :'tino',
      say: function(){
        console.log('hi');
      },
      ok: syb,
      un: undefined
    }
    var copy = JSON.parse(JSON.stringify(person))

  方法2:

    写个函数递归复制
    function deepCopy(obj) {
      var result = Array.isArray(obj) ? [] : {};  //Array.isArray(object) 检测是否为数组 传进来的object是数组,返回true,如果不是数组,则返回false
      for (var key in obj) {
        if (obj.hasOwnProperty(key)) {
          if (typeof obj[key] === 'object' && obj[key]!==null) {
            result[key] = deepCopy(obj[key]); //递归复制
          } else {
            result[key] = obj[key];
          }
        }

      }
      return result;
    }  

 

六、https使用iframe嵌入http资源的问题(了解,未使用)


  目前现象:
    https 网站 使用iframe嵌入http资源网站的内容,会弹出“是否加载不安全的内容”的提示,点击“加载”按钮后显示正常。
    对用户来说显示不友好。

  问题原因:
            https中使用http的资源时,浏览器会认为可能会不安全, 会自动弹出“是否加载不安全的内容”的提示。
            该提示由浏览器自动弹出,不能通过修改代码的方式解决。
            https中使用https资源时,如果https资源不安全,同样会报错。

    尝试解决方案:
             1) 使用自定义ssl证书,将http资源模拟成为https
                   使用nginx或者apache服务器,将http协议的资源包装为https协议的资源使用,前提条件是nginx或者apache服务器可以同时访问到http的资源和https的资源,将http链接地址从原网站改为nginx或apache包装的https的地址即可。
                   否则会报错“ 因为没有使用有效的安全证书进行签名,该内容已被屏蔽”的新错误提示。
             2)使用第三方签名的ssl证书,将http资源转换成为https
                      和方案1相同,但是使用第三方签名CA证书,网站可以正常访问。
                     但是第三方的CA签名的ssl证书是需要按年付费的, 价格 从每年几百到每年几千元均有。
             3)   要求http网站资源提供https的格式内容,且使用的ssl证书为第三方CA签名证书。

  

 

七、当在 element ui 使用 resetFields()重置表单后,表单无法输入的问题


  this.$refs[formName].resetFields(); 使用后部分表单无法输入

  解决:

    resetFields 是对整个表单进行重置,讲所有字段值重置为"初始值",并移除校验结果.
    所以给表单默认一个初始值就可以解决

 

八、vue中子组件的created、mounted钩子中获取不到props中的值问题

  当props中接受的值是动态获取的,这种情况下,钩子中是取不到值的,或者取到的一直是默认值。

  原因:
    出现这种情况的原因, 因为父组件中的要就要传递的 props 属性 是通过 发生ajax请求回来的,
    请求的这个过程是需要时间的,但是“子组件的渲染要快于ajax请求过程”,所以此时 created 、 mounted 这样的只会执行一次的生命周期钩子,已经执行了,但是 props 还没有流进来(子组件),所以只能拿到默认值。

  解决:

    使用watch处理,监听 传入的值,当它由空转变时就会触发,这时候就能取到了,created、mounted,中依旧拿不到值拿到值后要做的处理方法也需要在 watch 里面执行。

 

九、在vue的dialog中嵌套dialog,弹出里层的dialog时,发现被dialog的遮罩层挡住了  

  解决:
    对于确实需要嵌套 Dialog 的场景,提供了append-to-body属性。将内层 Dialog 的该属性设置为 true,它就会插入至 body 元素上,从而保证内外层 Dialog 和遮罩层级关系的正确。

 

十、对接七陌外呼系统

  引入插件:

  import md5 from 'js-md5'; //md5加密
  let Base64 = require("js-base64").Base64; //转化base64 https://www.javascriptcn.com/read-41473.html
  import moment from "moment"; //用于获取时间戳 http://momentjs.cn/docs/

  //外呼接入函数(依据七陌接口文档 https://developer.7moor.com/v2docs/dialout/)
      

   callOut(val) {
        const exten = "8003";  //坐席工号
        const ACCOUNTID = "N00000037833"; //账户编号(ACCOUNTID)
        const APISecret = "1e86bcb0-fbc0-11e9-833b-1f632fa2b92c";  //帐号APISecret
        const timestamp = moment().format("YYYYMMDDHHmmss");//获取当前时间的时间戳

        const sig = md5(`${ACCOUNTID}${APISecret}${timestamp}`).toUpperCase(); //url参数sig的值为 32位大写MD5加密 (帐号Id + 帐号APISecret +时间戳)
        const auth = Base64.encode(`${ACCOUNTID}:${timestamp}`);  //Authorization是包头验证信息 Authorization的值为 Base64编码(账户Id +冒号+时间戳) 

        this.$axios({
          method: 'POST',
          url: `/7moor/v20160818/call/dialout/${ACCOUNTID}?sig=` + sig,
          data: {
            FromExten: exten, //坐席工号
            Exten: val.customer_mobile, //外呼的电话号码
            ExtenType: "sip" //座机方式
          },
           headers: {
              "Content-Type""application/json;charset=utf-8",
              'Authorization': auth
            }
        }).then((res) => {
          console.log(res)
        })
      },


    跨域问题详解: https://www.jianshu.com/p/a0dd1e712c3a
    请求会出现跨域的问题:config/index.js 配置本地跨域代理,上线时需要配置nginx代理
    

        proxyTable: {
          '/7moor': {
            target: 'https://apis.7moor.com',
            changeOrigin: true,
            pathRewrite: {
              '^/7moor': '/' //实际请求去掉 /7moor 以  / 代替
            }
          }
        },

配置表

    dev: {
          // 静态资源文件夹
          assetsSubDirectory: 'static',

          // 发布路径
          assetsPublicPath: '/',

          // 代理配置表,在这里可以配置特定的请求代理到对应的API接口
          // 例如将'localhost:8080/api/xxx'代理到'www.example.com/api/xxx'
          // 使用方法:https://vuejs-templates.github.io/webpack/proxy.html
          proxyTable: {
            '/api/cms': {
              target: 'http://localhost:31001',
              pathRewrite: {
                '^/api': ' '   //实际请求去掉/api以空字符串代替

              }
            }
          },

 

 十一、用postcss-px2rem插件,样式中px强制不自动转换为rem的方法

  

#box {
   height: 44px  
   width: 100%
   font-size: 24px;/*no*/      //如果不想用插件转换可以用/*no*/标识符
}

 

问题:当打包编译过 之后 /*no*/这个标签会被当成注释给去掉,
解决:把px改成PX大写,浏览器一样识别,px2rem不会转换它。

 

 

 


十二、vue中在data中引入图片的路径方法

   ---错误的引入方式:
        export default {
            data () {
                return{
                    imgUrl_homePage:'@/assets/img/homePage_active.png'
                }
            }
        }
    ---import在外部引入
    import img_url from '@/assets/img/homePage_active.png'
    export default {
        data () {
            return{
                imgUrl_homePage:img_url
            }
        }
    }
    ---require内部引入
    export default {
        data () {
            return{
                imgUrl_homePage:require('@/assets/img/homePage_active.png')
            }
        }
    }

 

十三、使用vant中van-list插件时为什么 List 初始化后会立即触发 load 事件?

List 初始化后会触发一次 load 事件,用于加载第一屏的数据,这个特性可以通过immediate-check属性关闭。
loading 的设置也会影响到load事件的触发

 

十四、依据一个对象属性的值,判断这个数组是否含有这个对象,有的话删除,没有的话增加

const ind = this.chooseSelectedPrice.findIndex(
    item => item.value === priceWen
);
if (ind !== -1) {
    this.chooseSelectedPrice.splice(ind, 1);
} else {
    if (this.qieNum2 === 0) {
    this.chooseSelectedPrice.push({
        value: priceWen,
        start: item.start,
        end: item.end,
        type: 0
    });
    } else {
    this.chooseSelectedPrice.push({
        value: priceWen,
        start: item.start,
        end: item.end,
        type: 1
    });
    }
}

 

十五、数组的切割中arr.splice(n,1)

  使用时不可let arr2 = arr.splice(n,1)  因为它是改变原数组的,不会有返回值

十六、localStorage本地存储时,key值不能为变量,可以通过以下方法变通

obj[phone] = JSON.stringify(celPhone);
this.$tool.setStorage(obj);//集成的方法

delete celPhone[buildingId];

 

十七、关键字搜索高亮

pushHTML(text, str) {
    let arr = str.split(text);
    let newText = arr.join('<span style="color:#00A4FF">' + text + "</span>");
    return newText;
},

 

十八、router-link 绑定事件不生效

  加 .native 修饰符就可以执行事件了。
  <router-link to="/date" @click.native="nav_click">最新</router-link>
  原因:
    1: 因为它是自定义标签,根本就没有事件和方法,所以不触发,加个native 就是告诉vue 这个标签现在有主了 它是H5标签 可以加事件了。

    2:父组件要想在子组件监听自己的click事件就得加native,router-link是标签啊。哪里有父组件????

    router-link 其实就是一个封装好的 .vue 组件,所以需要 加.native修饰符才能绑定事件

 

十九、vue跳转当面页面(页面路径不变化,携带参数改变)页面不刷新问题 

  解决1、router-view 中加一个 key
    <router-view :key="$route.fullPath" />

  解决2、路由改变时刷新当前页
    this.$router.go(0);

    vue 框架this.$router.go(0) safari 浏览器不刷新
    用原生 window.location.reload()

二十(粗心)当用组件,时,用到v-model,或者动态绑定的值,无效时,要看清当前组件需要绑定的值得类型,好多次,number类型的绑定成了string,死活不出效果,调试很久,谨记。

     字符串定义  未赋值时不能使用,否则会报undefined

 

二十一、本地存储封装 

/* 获取浏览器存储里key为item的值
     @param item 要获取的数据的索引值
     Usage:
     helper.get('token')
     */
    function getStorage(item) {
        var value;
        value = window.localStorage.getItem(item)
        return (value ? decrypt(value) : '')
    }

    /* 将数据存储在浏览器存储里
     @param obj 要存储的数据对象
     Usage:
     j.set({ token: 'as23q1sdf212swsxx', uname: 'jacket' })
     */
    function setStorage(obj) {
        for (var key in obj) {
            if (obj.hasOwnProperty(key)) {
                window.localStorage.setItem(key, encrypt(String(obj[key])));
            }
        }
    }

 

 二十二、jquery获取参数 

detail.html?order_id=10

<Script language="javascript">  
    function GetRequest() {  
       var url = location.search; //获取url中"?"符后的字串  
       var theRequest = new Object();  
       if (url.indexOf("?") != -1) {  
          var str = url.substr(1);  
          strs = str.split("&");  
          for(var i = 0; i < strs.length; i ++) {  
             theRequest[strs[i].split("=")[0]]=unescape(strs[i].split("=")[1]);  
          }  
       }  
       return theRequest;  
    }  
    </script> 


detail.html?order_id=10&uid=3

function GetRequest() {
    var url = location.search; //获取url中"?"符后的字串
    var theRequest = new Object();
    if (url.indexOf("?") != -1) {
        var str = url.substr(1);
        strs = str.split("&");
        console.log(strs)
        for (var i = 0; i < strs.length; i++) {
            theRequest[strs[i].split("=")[0]] = decodeURIComponent(strs[i].split("=")[1]);
        }
    }
    return theRequest;
}

 

 二十三、jquery给元素增加一个父元素

     let d = $("table").clone(); //clone(includeEvents) 方法生成被选元素的副本,包含子节点、文本和属性。 includeEvents 可选。布尔值。规定是否复制元素的所有事件处理。 默认地,副本中不包含事件处理器。
        let f = $("table").parent();
        console.log(d,f)
        $("table").remove();
        $(f).append("<div class='kg'><div>");
        $(".kg").html(d)

 

 以上为沙雕做法而且有bug
$('table').wrap("<div class='kg'></div>");一句搞定它不香么

二十四、整行字体渐变色

    .title span {
      background: linear-gradient(135deg,#f2e1b5, #fff3d6 33%, #e8ce91);
      -webkit-background-clip:text;
      color:transparent;
    }
 
 
二十五、css3 之image之object-fit作用
//默认值。替换内容拉伸填满整个content box, 不保证保持原有的比例。
object-fit: fill;
 
//保持原有尺寸比例。保证替换内容尺寸一定可以在容器里面放得下。因此,此参数可能会在容器内留下空白。
object-fit: contain;
 
//保持原有尺寸比例。保证替换内容尺寸一定大于容器尺寸,宽度和高度至少有一个和容器一致。
//因此,此参数可能会让替换内容(如图片)部分区域不可见
object-fit: cover;
 
//保持原有尺寸比例。同时保持替换内容原始尺寸大小。
object-fit: none;
 
//最终呈现的是尺寸比较小的那个,类似于依次设置none或contain。
object-fit: scale-down;

 htmljs锚点滚动

function scrollDom() {
    allHeights = [];
    $(".activity_main_li").each((index, item) => {
        let top = '',
            s = $("." + $(item).attr("currentname"));
        allHeights.push(s.offset().top)
    })
    $(window).scroll(function() {
        scrollTopDom()
    })

};

function scrollTopDom() {
    // 获取当前滚动的高度
    var top = document.body.scrollTop + document.documentElement.scrollTop;
    top = top + 90;
    if (review) {
        review = false;
        scrollHeight = document.body.scrollHeight;
    }
    let index = 0;
    if (top >= allHeights[allHeights.length - 1]) {
        index = allHeights.length - 1
    } else {
        $(allHeights).each((i, res) => {
            if (top < res && top > allHeights[i - 1]) return index = i - 1
        })
    }
    if (currentPoint != index && !currentGun) {
        currentPoint = index;
        $(".activity_main_li").removeClass("active");
        $($(".activity_main_li")[index]).addClass("active")
        scrollX(index)
    }
    // 滚动条距离顶部的距离 大于 200px时
    if (top >= 500 && flag) {
        flag = false;
        $(".activity_main_title").css({
            "position": "fixed",
            "top": "0",
            "z-index": "9",
            "background-color": "#0E0E0E"
        });
    } else if (top < 500) {
        flag = true;
        $(".activity_main_title").css({
            position: 'relative',
            backgroundColor: 'transparent'
        });
    }
}


//点击切换锚点链接
function clickMao() {
    $(".activity_main_li").each(function(i, item) {
        $(item).click(function(e) {
            $(".activity_main_li").removeClass("active")
            $(this).addClass("active");
            let id = $(this).attr("currentName");
            currentGun = true;
            let to = allHeights[i] - 45;
            scrollX(i)
            $('html,body').animate({
                scrollTop: to
            }, 500)
            setTimeout(_ => {
                currentGun = false;
            }, 600)
        })
    })
}

//标签横向滚动
function scrollX(index) {
    let MarL = $(".activity_main_li").width() * index - 80
    $('.activity_main_ul').animate({
        scrollLeft: MarL
    }, 200)
}
 

 

&&&&&&&&&&&&&&&&&&&《项目中的知识点》&&&&&&&&&&&&&&&&&&&&&&&&

 

1、hasOwnProperty:
  hasOwnProperty()方法返回一个布尔值,判断对象是否包含特定的自身(非继承)属性。
  function Person(name, age) {
    this.name = 'Tom';
    this.age = 11;
  };
  Person.prototype = {
    job:'资深前端开发工程师',
  };
  console.log(Person.hasOwnProperty('name'))//true
  console.log(Person.hasOwnProperty('job'))//false

 

2、JSON.stringify()
  JSON 通常用于与服务端交换数据。
  在向服务器发送数据时一般是字符串。
  我们可以使用 JSON.stringify() 方法将 JavaScript 对象转换为字符串。
JSON.parse()
  JSON 通常用于与服务端交换数据。
  在接收服务器数据时一般是字符串。
  我们可以使用 JSON.parse() 方法将数据转换为 JavaScript 对象。

 

3、localStorage

  localStorage 可以在浏览器中存储键值对的数据,能长期储存
  localStorage中的键值对总是以字符串的形式存储,并且只能访问当前域名下的数据,不能跨域名访问

  可以通过setItem方法增加了一个键值对数据,如果该键已存在,那么该键对应的值将被覆盖
    localStorage.setItem("name","xiaozhong")

  可以用getItem方法读取对应键的值数据
    localStorage.getItem("name")

  可以用removeItem方法移除对应键
    localStorage.removeItem("name")

  可以用clear方法移除当前域名下所有的键值对数据
    localStorage.clear()

posted @ 2019-12-25 17:21  张小中  阅读(829)  评论(1编辑  收藏  举报