0318-0409笔记
JSON.parse()与JSON.stringify()
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() 方法送出
用途:
- 用一些键值对来模拟一系列表单控件:即把form中所有表单元素的name与value组装成一个
queryString
- 异步上传二进制文件
用法:
-
创建空对象,通过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){ //... } }
-
对表单进行初始化
<form id="advForm"> <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 id="file" type="file" name="file"></p> <p><input type="button" id="btn" value="添加"></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){
//...
}
}
}
操作方法
-
通过get(key)与getAll(key)来获取相对应的值
// 获取key为age的第一个值 formdata.get("age"); // 获取key为age的所有值,返回值为数组类型 formdata.getAll("age");
-
通过set(key, value)来设置或修改数据
- key的值不存在,会添加一条数据
- key的值存在,会修改对应的value值
-
通过append(key,value)在数据末尾追加数据
//通过FormData构造函数创建一个空对象 var formdata=new FormData(); //通过append()方法在末尾追加key为name值为laoliu的数据 formdata.append("name","laoliu");
-
通过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
-
通过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有两种声明方式,然后在引用的时候加上
-
局部声明
filters: { Upper: function (value) { return value.toUpperCase() } }
应用: {{data | Upper}}
-
全局声明
Vue.filter('toUSD', function (value) { return `$${value}` })
应用: {{data | toUSD}}
传参和串联
-
传参
一般第一个参数就是将要被过滤的数据,后面的第二个,第三个……是自己可以传的// 这个过滤器传了三个参数: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 id="app"> <div class="summary">{{ data | readMore(20, '...') }}</div> <a :href="link">阅读更多</a> </div>
上面的代码表示了,当超出20个字时显示省略号
-
串联
所谓的串联,就是在前一个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 id="app"> <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)
}
获取数组的和
-
不考虑算法复杂度,用递归做
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)); } }
-
常规循环
function sum(arr) { var s = 0; for (var i=arr.length-1; i>=0; i--) { s += arr[i]; } return s; }
-
函数式编程 map-reduce
function sum(arr) { return arr.reduce(function(prev, curr, idx, arr){ return prev + curr; }); }
-
forEach遍历
function sum(arr) { var s = 0; arr.forEach(function(val, idx, arr) { s += val; }, 0); return s; }
-
eval
function sum(arr) { return eval(arr.join("+")); }
只能输入单词,下划线,数字
var reg = /^[a-zA-Z\d_]*$/
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
- 2017-01-01 12:00:00
Safari中不支持'-'格式的日期字符串,将其替换成'/' 变成2017/01/01 12:00:00即可正常使用 - 2017/01/01T11:00:00
此格式的日期字符串在Safari中也是不得到支持的,需要将字符串中的'T' 替换成空格
解决方法: let time = new Date(Date.parse(val.replace(/-/g,'/').replace(/T/,' ')))
打开新窗口和在当前页面打开窗口
- 当前页面打开窗口
window.location.href = 'xxxx' - 打开新窗口
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为允许;
火狐浏览器在切换中英版时,有的无法切换
经过观察,是火狐在第一次加载时,形成了缓存,所以在切换时数据是从缓存中读取的,没有发起新的请求。
解决办法:
-
'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) 返回是什么
-
一元加法运算符把操作数转换为数字(或NaN),并返回这个转换后的数字。如果操作数本身就是数字,则直接返回这个数字。
-
new Array(017)中的017是八进制表示,对应的十进制为15,即为一个有15个元素的数组。
-
这段代码要做的是尝试将此数组转换为数字。
-
数组是对象的特殊形式。对象到数字的转换首先会尝试使用valueOf(),若不是返回的原始值则调用toString()方法。
-
数组继承了默认的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) //进入到这个页面时,自动播放到第二张
}
思路:
- 声明ref,绑定组件
- 将name值绑定,根据文档setActiveItem方法说明需要切换的幻灯片的索引,从0开始;或相应el-carousel-item的name属性值,我这里通过name来进行参数传递,来进行切换。
- 可以在某个地方调用这个setActiveItem方法。