0318-0409笔记 JSON.parse()与JSON.stringify() new FormData v-if和v-for同时使用的影响 vue的filter 在mounted使用获取某个元素的高度时,获取子组件的高度,用ref获取不到,用常用类名的方式获取,用完记得销毁,否则其他页面会出现offsetHeight为null。 用destroyed销毁一些监听事件及定时函数 获取数组的和 只能输入单词,下划线,数字 往对象添加属性和值以及删除属性 判断数据是否在数组中 获取时间 safari时间格式化不识别yyyy-mm-dd,会返回NaN 打开新窗口和在当前页面打开窗口 火狐浏览器在切换中英版时,有的无法切换 +new Array(017) 返回是什么 flash和js通过什么类进行交互? new String() 和 String elementui的el-carsouel的手动切换幻灯片(setActiveItem方法)

JSON.parse() 从一个字符串中解析成对象

  var json = '{"name":"goatling"}'
  var data = JSON.parse(json) // {name: "goatling"}

eg: json字符串必须是外部单引号,内部双引号,否则会报错Uncaught SyntaxError: Unexpected token ' in JSON at position 1

JSON.stringify() 将对象解析成字符串

  var data = {name: "goatling"}
  var json = JSON.stringify(json) // "{"name":"goatling"}"

拓展:

atob与btoa
btoa和atob是window对象的两个函数

  • btoa是binary to ascii,用于将binary的数据用ascii码表示,即Base64的编码过程,叫编码

  • atob则是ascii to binary,用于将ascii码解析成binary数据,叫解码

    var string = 'Hello World!';
    var encodedString = btoa(string);  
    console.log(encodedString);  // "SGVsbG8gV29ybGQh"
    
    var decodedString = atob(encodedString);
    console.log(decodedString);   // "Hello World!"
    

eg: atob和btoa不能编码Unicode字符(汉字),可以使用encodeURIComponent和decodeURIComponent

    var string = "Hello, 中国!";
    //"SGVsbG8lMkMlMjAlRTQlQjglQUQlRTUlOUIlQkQlRUYlQkMlODE="
    var encodedString = btoa(encodeURIComponent(string));
    var decodedString = decodeURIComponent(atob(encodedString));
    console.log(decodedString); //"Hello, 中国!"

eg:编码的过程是先encodeURI,再编码,那么解码的过程应该是先解码,再decodeURI。
IE9不支持atob和btoa。

拓展:encodeURI、encodeURIComponent、decodeURI、decodeURIComponent
统一资源标识符,或叫做 URI,是用来标识互联网上的资源(例如,网页或文件)和怎样访问这些资源的传输协议(例如,HTTP 或 FTP)的字符串。
说白了就是对url的编码和解码。
encodeURI/decodeURI 只针对于部分的编码与解码,如^
encodeURIComponent/decodeURIComponent,大部分都能进行编码与解码

new FormData

FormData 接口提供了一种表示表单数据的键值对的构造方式,经过它的数据可以使用 XMLHttpRequest.send() 方法送出

用途:

  1. 用一些键值对来模拟一系列表单控件:即把form中所有表单元素的name与value组装成一个queryString
  2. 异步上传二进制文件

用法:

  1. 创建空对象,通过append方法追加数据

     var formdata=new FormData();
     formdata.append("name","laotie");
     var xhr=new XMLHttpRequest();
     xhr.open("post","http://127.0.0.1/adv");
     xhr.send(formdata);
     xhr.onload=function(){
         if(xhr.status==200){
             //...
         }
     }
    
  2. 对表单进行初始化

     <form >
       <p>广告名称:<input type="text" name="advName"  value="xixi"></p>
       <p>广告类别:<select name="advType">
           <option value="1">轮播图</option>
           <option value="2">轮播图底部广告</option>
       </select></p>
       <p>文件:<input ></p>
       <p><input type="button" ></pp>
     </form>
    

通过表单元素作为参数,实现对formData的初始化:

    //获得表单按钮元素
    var btn=document.querySelector("#btn");
    // 文件元素
    var file = document.querySelector('[type=file]');
    //为按钮添加点击事件
    btn.onclick=function(){
        //根据ID获得页面当中的form表单元素
        var form=document.querySelector("#advForm");
        //将获得的表单元素作为参数,对formData进行初始化
        var formdata=new FormData(form); // 通过FormData将文件转成二进制数据
        // 将文件转二进制
        formdata.append('upload', file.files[0]);
        var xhr=new XMLHttpRequest();
        xhr.open("post","http://127.0.0.1/adv");
        // 监听上传进度
        xhr.upload.onprogress = function (ev) {
          // 事件对象
          var percent = (ev.loaded / ev.total) * 100 + '%';
          progress.style.width = percent;
        }
        xhr.send(formdata);
        xhr.onload=function(){
            if(xhr.status==200){
                //...
            }
        }
    }

操作方法

  1. 通过get(key)与getAll(key)来获取相对应的值

     // 获取key为age的第一个值
     formdata.get("age"); 
     // 获取key为age的所有值,返回值为数组类型
     formdata.getAll("age");
    
  2. 通过set(key, value)来设置或修改数据

    • key的值不存在,会添加一条数据
    • key的值存在,会修改对应的value值
  3. 通过append(key,value)在数据末尾追加数据

     //通过FormData构造函数创建一个空对象
     var formdata=new FormData();
     //通过append()方法在末尾追加key为name值为laoliu的数据
     formdata.append("name","laoliu");
    
  4. 通过has(key)来判断是否存在对应的key值

     //通过FormData构造函数创建一个空对象
     var formdata=new FormData();
     //通过append()方法在末尾追加key为name值为laoliu的数据
     formdata.append("name","laoliu");
     //判断是否包含key为name的数据
     console.log(formdata.has("name"));//true
     //判断是否包含key为age的数据
     console.log(formdata.has("age"));//false
    
  5. 通过delete(key)可以删除数据

     //删除key为name的值
     formdata.delete("name");
     console.log(formdata.get("name"));//null
    

v-if和v-for同时使用的影响

当 v-if 与 v-for 一起使用时,v-for 具有比 v-if 更高的优先级,当它们处于同一节点,由于v-for 的优先级比 v-if 更高,这意味着 v-if 将分别重复运行于每个 v-for 循环中。

  • 当你想为仅有的一些项渲染节点时,这种优先级的机制会十分有用。

    <li v-for="todo in todos" v-if="!todo.isComplete">
      {{ todo }}
    </li>
    

    上面的代码只传递了未完成的 todos。

  • 如果你的目的是有条件地跳过循环的执行,那么可以将 v-if 置于外层元素 (或 < template >)上

    <ul v-if="todos.length">
      <li v-for="todo in todos">
        {{ todo }}
      </li>
    </ul>
    <p v-else>No todos left!</p>
    

vue的filter

声明方式

vue的filter有两种声明方式,然后在引用的时候加上

  1. 局部声明

     filters: { 
       Upper: function (value) { 
         return value.toUpperCase() 
       } 
     }
    

应用: {{data | Upper}}

  1. 全局声明

     Vue.filter('toUSD', function (value) { 
       return `$${value}` 
     })
    

应用: {{data | toUSD}}

传参和串联

  1. 传参
    一般第一个参数就是将要被过滤的数据,后面的第二个,第三个……是自己可以传的

       // 这个过滤器传了三个参数:text, length, suffix 
       Vue.filter('readMore', function (text, length, suffix) { 
         return text.substring(0, length) + suffix 
       })
       let app = new Vue({
         el:'#app',
         data () {
           return {
             data:'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
             link: 'xxxxxxx'
           }
         }
       })
    
       <div >
         <div class="summary">{{ data | readMore(20, '...') }}</div>
         <a :href="link">阅读更多</a>
       </div>
    

    上面的代码表示了,当超出20个字时显示省略号

  2. 串联
    所谓的串联,就是在前一个filters上再加上filters,通过 | 进行串联

       Vue.filter('toFixed', function (price, limit) {
         return price.toFixed(limit)
       })
    
       Vue.filter('toUSD', function (price) {
         return `$${price}`
       })
    
       let app = new Vue({
         el: '#app',
         data () {
           return {
             price: 435.333
           }
         }
       })
    
    
       <div >
         <h1>{{ price | toFixed(2) | toUSD }}</h1>
       </div>
    

    上面的代码表示了,将价钱保留两位小数,并且加上单位

在mounted使用获取某个元素的高度时,获取子组件的高度,用ref获取不到,用常用类名的方式获取,用完记得销毁,否则其他页面会出现offsetHeight为null。 用destroyed销毁一些监听事件及定时函数

  methods: {
    handleScroll(){
      let scrollTop = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop
      var breadHeight = document.querySelector(‘abc’)
      if(scrollTop > 1000)
      {
          // -----
      }
    }
  }  
  mounted(){// 判断滚动某个阶段触发scroll
    window.addEventListener(’scroll’,this.handleScroll)
  }
  destroyed(){// 离开页面时销毁事件
    window.removeEventListener(’scroll’,this.handleScroll)
  }

获取数组的和

  1. 不考虑算法复杂度,用递归做

     function sum(arr) {
       var len = arr.length;
       if(len == 0){
           return 0;
       } else if (len == 1){
           return arr[0];
       } else {
           return arr[0] + sum(arr.slice(1));
       }
     }
    
  2. 常规循环

     function sum(arr) {
       var s = 0;
       for (var i=arr.length-1; i>=0; i--) {
           s += arr[i];
       }
       return s;
     }
    
  3. 函数式编程 map-reduce

     function sum(arr) {
       return arr.reduce(function(prev, curr, idx, arr){
           return prev + curr;
       });
     }
    
  4. forEach遍历

     function sum(arr) {
       var s = 0;
       arr.forEach(function(val, idx, arr) {
           s += val;
       }, 0);
       return s;
     }
    
  5. eval

     function sum(arr) {
       return eval(arr.join("+"));
     }
    

只能输入单词,下划线,数字

var reg = /^[a-zA-Zd_]*$/
if(reg.test(val)) console.log('error')

往对象添加属性和值以及删除属性

  • 添加

    var obj = {}
    obj.item = 'peter'
    
  • 删除

    var obj = {
      name: 'peter',
      age: 25
    }
    delete obj.name
    console.log(obj) // {age:25}
    

判断数据是否在数组中

function isInArray(arr,obj){
  let l = arr.length
  while(l—-){
    if(arr[i] == obj){
      return true
    }
  }
  return false
}

获取时间

  var date = new Date();//获取系统当前时间
  date.getYear(); //获取当前年份(2位)
  date.getFullYear(); //获取完整的年份(4位,1970-????)
  date.getMonth(); //获取当前月份(0-11,0代表1月)
  date.getDate(); //获取当前日(1-31)
  date.getDay(); //获取当前星期X(0-6,0代表星期天)
  date.getTime(); //获取当前时间(从1970.1.1开始的毫秒数)
  date.getHours(); //获取当前小时数(0-23)
  date.getMinutes(); //获取当前分钟数(0-59)
  date.getSeconds(); //获取当前秒数(0-59)
  date.getMilliseconds(); //获取当前毫秒数(0-999)
  date.toLocaleDateString(); //获取当前日期
  var time=date.toLocaleTimeString(); //获取当前时间
  date.toLocaleString( ); //获取日期与时间

safari时间格式化不识别yyyy-mm-dd,会返回NaN

  1. 2017-01-01 12:00:00
    Safari中不支持'-'格式的日期字符串,将其替换成'/' 变成2017/01/01 12:00:00即可正常使用
  2. 2017/01/01T11:00:00
    此格式的日期字符串在Safari中也是不得到支持的,需要将字符串中的'T' 替换成空格

解决方法: let time = new Date(Date.parse(val.replace(/-/g,'/').replace(/T/,' ')))

打开新窗口和在当前页面打开窗口

  1. 当前页面打开窗口
    window.location.href = 'xxxx'
  2. 打开新窗口
    window.open('xxxx')

window.open() 是window的一个方法,而location是window的属性
window.open()弹出新窗口的属性如下:

  • '链接地址' 弹出窗口的文件名;
  • 'newwindow' 弹出窗口的名字(不是文件名),非必须,可用空''代替;
  • height=100 窗口高度;
  • width=400 窗口宽度;
  • top=0 窗口距离屏幕上方的象素值;
  • left=0 窗口距离屏幕左侧的象素值;
  • toolbar=no 是否显示工具栏,yes为显示;
  • menubar,scrollbars 表示菜单栏和滚动栏。
  • resizable=no 是否允许改变窗口大小,yes为允许;
  • location=no 是否显示地址栏,yes为允许;
  • status=no 是否显示状态栏内的信息(通常是文件已经打开),yes为允许;

火狐浏览器在切换中英版时,有的无法切换

经过观察,是火狐在第一次加载时,形成了缓存,所以在切换时数据是从缓存中读取的,没有发起新的请求。
解决办法:

  1. 'Cache-Control': 'no-cache'

     const service = axios.create({
       headers: {
           'Cache-Control': 'no-cache'
       }
     })
    

以上无效。。。。。。。
2. 添加时间戳(require.js)
axios.interceptors.request.use(config => {
config.headers['Authorization'] = Cookies.get('token'); //传入token
config.headers['language'] = local; //传入语言参数
//------------------增加时间戳------------------
config.params = {
_t: Date.parse(new Date())/1000,
...config.params
}
//---------------------------------------------
return config;
}, error => {
//发送请求错误操作
iView.Message.error('error:'+error.message);
return Promise.reject(error);
})

+new Array(017) 返回是什么

  1. 一元加法运算符把操作数转换为数字(或NaN),并返回这个转换后的数字。如果操作数本身就是数字,则直接返回这个数字。

  2. new Array(017)中的017是八进制表示,对应的十进制为15,即为一个有15个元素的数组。

  3. 这段代码要做的是尝试将此数组转换为数字。

  4. 数组是对象的特殊形式。对象到数字的转换首先会尝试使用valueOf(),若不是返回的原始值则调用toString()方法。

  5. 数组继承了默认的valueOf()方法,这个方法会返回一个对象而不是一个原始值(undefined,null,Boolean,number,string)。因此数组到数字的转换则调用toString()方法

     typeof([1,2].valueOf());  //"object" 
     [1,2].toString();  //"1,2" 
     +"1,2";  //NaN
    

    所以结果为NaN

flash和js通过什么类进行交互?

Flash提供了ExternalInterface接口与JavaScript通信,ExternalInterface有两个方法,call和addCallback,

  • call的作用是让Flash调用js里的方法,
  • addCallback是用来注册flash函数让js调用。

new String() 和 String

JS里面的String的初始化有两种方式,直接赋值和String对象的实例化。

  • 直接赋值

    var str = 'abc'
    typeof str  == 'string' // true
    str instanceof String  // false
    
  • String对象的实例化

    var str1 = new String('abc')
    typeof str1 == 'string'  // false
    str1 instanceof String  // true
    

elementui的el-carsouel的手动切换幻灯片(setActiveItem方法)

  <template>
    <el-carousel indicator-position="none" autoplay='false' ref="carousel">
        <el-carousel-item name ='first' v-for="(item,index) in data" :key=index :name="item.id">
            <h3>item</h3>
        </el-carousel-item>
    </el-carousel>
    <el-button @click="click">
  </template>

  methods: {
    setActiveItem(index) {
      this.$refs.carousel.setActiveItem(index);
    },
    click () {
      // 假设name取得值是60,70,77
      this.setActiveItem(70) // 代表切换到70的那张
    }
  }
  created (){
    // this.setActiveItem(2) //进入到这个页面时,自动播放到第二张
  }

思路:

  1. 声明ref,绑定组件
  2. 将name值绑定,根据文档setActiveItem方法说明需要切换的幻灯片的索引,从0开始;或相应el-carousel-item的name属性值,我这里通过name来进行参数传递,来进行切换。
  3. 可以在某个地方调用这个setActiveItem方法。