每天解决一个问题,也会使自己进步一小步.
用新变量接收对象的时候是指针复制,当原对象的内容改变的时候新变量的指向虽然没变但是值已经变了,会导致值得错误。
解决办法: 深拷贝
具体代码:1
JSON.parse(JSON.stringify(object))
如何检测vueRouter的参数变化?
解决办法: 1.用watch监听$route对象2.使用beforeRouterUpdate(导航卫士),表示路由正在发生变化。
具体代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16// 方法一
watch:{
$route(to, from){
this.newPath = to
this.newParams = this.$route.query.oldValue
}
}
// 方法二 此方法知能监听路由路径
// to: Route: 即将要进入的目标 路由对象
// from: Route: 当前导航正要离开的路由
// next: Function: 一定要调用该方法来 resolve 这个钩子。执行效果依赖 next 方法的调用参数。
beforeRouterUpdate(to, from, next){
this.newPath = to
}关于img的src路径问题:获取到的路径是绝对路径直接填入了img的src中,控制台报错,不允许直接读取本地文件。
问题原因:前端不能通过浏览器直接访问硬盘上的文件,这样会有安全问题。
引申概念: file协议:读取本地文件用到的协议,对标http(s),http是加载网路资源用到的,速度慢。file协议是加载本地文件用到的速度快。数组的:indexOf、includes、find、findIndex、lastIndexOf。这几个知道是干什么用的但是返回值又忘了,加深记忆一下。
返回值区别: indexOf 存在返回下标,不存在返回-1includes 包含返回true,不包含返回false find 返回满足填入函数的第一个值,否则返回false findIndex 返回满足填入函数的第一个值的下标,否则返回-1 lastIndexOf 返 回指定元素在数组中的最后一个的位置。不存在则返回-1。(查找顺序从后向前查找,但是下标还是从头开始算起)
BEM,Block(块)、Element(元素)、Modifier(修饰符)
BEM命名规范:- : 中划线。仅作为连字符使用,表示某个块或者元素之间多个单词的连接记号 __ : 双下划线。用来连接块和块的子元素 _ : 单下划线。用来描述一个块或者块的子元素的一种状态。
例: .block__element–midifier
如何获取到Object的key
API: Object.keys() 。返回的是由key组成的一个数组。1
Object.keys(obj) // obj要被枚举自身属性的对象
vue里的mixin(混入)功能经常导致变量赋值的位置不好确定。
for…in 和 for…of的区别:
for…in是ES5的语法,遍历对象属性的时候,使用。
for…of是ES6的语法,遍历数组时候使用。不能循环普通的对象。for of 只能遍历可迭代的可迭代属性,不可迭代的属性被忽略了。
1
2
3
4
5
6
7
8
9
10Object.prototype.objCustom = function () {};
Array.prototype.arrCustom = function () {};
let iterable = [3, 5, 7];
iterable.foo = "hello";
for (let i in iterable) {
console.log(i); // logs 0, 1, 2, "foo", "arrCustom", "objCustom"
}
for (let i of iterable) {
console.log(i); // logs 3, 5, 7
}URL编码解码:
- encodeURI:除了空格其他字符不做转译,空格转译成%20
decodeURI:翻译encodeURI转译后的字符串 - encodeURIComponent:除了字母数字以外的全部转译
decodeURIComponent:翻译encodeURIComponent的字符
- encodeURI:除了空格其他字符不做转译,空格转译成%20
函数的length属性是形参的个数,内部arguments的length是实参(实际调用时候传参的个数)
1
2
3
4
5function a(a,b,c){
return arguments.length
}
console.log(a.length) // 3 因为有三个形参
console.log(a(1,2)) // 2 因为有两个实参判断函数是不是通过new 创建的。
通过ES6的元属性(new.target)来判断。元属性指的是非对象的属性。
当调用函数的Construct方法时,new.target被赋为new操作的目标,通常是新创建的对象实例。也就是函数体内部的this。
如果调用Call方法,则new.target的值为undefined。
代码:1
2
3
4
5
6
7function Person(name) {
if(typeOf new.target === Person){
this.name = name
} else {
console.log('不是通过new调用的')
}
}Unexpected side effect in “xxx” computed property
原因:在computed里改变了data里的属性
解决办法:在computed里新建一个变量,操作新建的变量。ES6深拷贝数组:
代码:1
2let array = [1,2,3,4,5]
let [...newArray] = array // 此时的newArray就是深拷贝vue里的computed(计算属性)里不能调用异步方法
箭头函数
特性:没new.target属性,不能当构造函数,this指向外部调用者,没有construct属性,没有argument对象。尾调用优化条件:
- 不调用栈帧(stack frame)里的局部变量
- 函数调用是否在尾部发生
- 最后retrun的是否是函数
能优化的点:
递归函数
vue 子组件更新父组件的值,emit和sync
1
2
3
4// 子组件内,想要修改父组件内自己的显隐
this.$emit('update:visible',false)
// 父组件内的子组件生命的属性里 ,最终结果dialogVisible为false
:visible.sync = 'dialongVisible'响应式原理——对象部分。在methods尝试给data里的一个对象添加新的属性,然后发现watch监听不到变化
原因:看了一下文档的’深入响应式原理’关于对象的部分。主要是因为vue无法监听property的添加或者移除,vue只会在初始化实例的时候对property执行setting和getting,所以property只有在data上存在才是响应式的。
解决办法:- 提前在data的对象中声明这个属性,给个默认值。
- 使用Set方法:
1
this.$Set(this.object, newKey, value)
响应式原理补充——数组部分
无法检测的操作:- 根据下标直接设置项
- 设置数组长度
1
2
3
4
5
6
7
8//引用官网例子
var vm = new Vue({
data: {
items: ['a', 'b', 'c']
}
})
vm.items[1] = 'x' // 不是响应性的
vm.items.length = 2 // 不是响应性的
解决办法:
- 还是set:
this.$Set(this.array, index,newValue) - splice方法
this.array.splice(index, 1,newValue) 修改值
this.array.splice(newLength) 修改长度
对象的深拷贝:
方法: Object.assign(target,…source).
注意点:属性限定简单类型。同名的属性会被覆盖(调用target的set和source的get)。box-sizing: 设置宽高是否包含border和padding
属性:- content-box:width和hight的属性只是content的部分,padding和border的单独算
- border-box:width和hight是content+padding+border的值。
margin和span标签:今天遇到的是想给span标签添加marign-bottom没生效。
原因:span标签是行内元素,- 直接设置margin-bottom和margin-top不生效。 - margin-left和margin-right生效。
解决办法:
对应的css属性内加入 'display:block',之后top和bottom就会生效。
元素居中解决方案:
1
2
3
4
5
6
7
8
9
10
11flex布局
#XXX{
display:flex;
justify-content:center;
}
IE8-9时
#XXX{
margin:0 auto;
}
以上属性全部设置到父元素上在watch中函数定义不能使用箭头函数.
用watch监听变量做到在mounted时候就能监听变化,需要加上immediate属性。
需要从后面匹配路径包含固定格式和固定单词
1
2// 用到的符号 *匹配零次或者多次、 | 或者、 符号转译需要在前面加 \、 匹配固定单词用\b
let regExp = /\/(a-z)*+\.(a-z)+\/(\bxxnnn\b|\bsss\b)$/ // /xx.xx/xxnnn or /xx.xx/sss正则表达式有效率问题,写完表达式注意测试用时。
文字过长处理方法:
1
2
3
4
5
6
7
8
9
10
11// html 部分
<span class="demo">1111<span>
// css 部分
.demo {
display: inline-block;
width: 100px
white-space: nowrap; // 不让文字换行
overflow: hidden; // 过长部分的处理方式
text-overflow: ellipsis; // 如何处理溢出部分
}复习:v-if更高的切换开销,v-show更高的初始化渲染开销。 v-if是惰性的,初始化条件为假的时候则什么也不做直到条件变为真,才会渲染条件块。
v-html使用注意点
<div v-html="html"></div>
- 等同于js原生的element.innerHTML()方法,可以插入html标签
- 不再用户能输入的地方使用,方式xss攻击(注入脚本)
- 组件内scope的样式,在v-html中不会生效因为没内容按普通 HTML 插入 - 不会作为 Vue 模板进行编译。
result | 0
超过32位的整数转换结果不等于自身,可用作溢出判断parseInt()
字符串转换数字。leetcode刷题用到的 字符串里有数字和字母。用这个提取数字。具体用法查询mdn的API。给变量设置默认值写法
1
let variableA = variableB || '' // 变量variableB隐形转换为false时,赋给variableA默认值为空字符串
小优化点:当用for查找某个条件时:查找到直接使用
break
跳出。减少循环次数。request method: options (个人理解:预请求)
意义:在浏览器的某些请求中,在正式通讯之前会增加一次HTTP查询请求,称为”预检”请求。通过这个方法客户端可以决定对该资源采取何种措施,或者了解服务器性能。只有得到肯定答复浏览器才会发送正式的请求。$refs只会在模板渲染完成后才生效且不是响应式的。应该避免在模板和计算属性中访问$refs
封装组件时,对功能有局限性的数据或者逻辑应该交给父组件传入或者处理,这样以后封装出来的组件更加的通用且好扩展。
时间相关的API: moment.js
Object.keys(obj) 返回obj的key组成的数组。
原型链:每个实例对象都有一个私有属性proto,他指向他的构造函数的原型对象(prototype),该原型也有自己的proto,层层向上指直到null,null是原型链的最后一环。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27function f(){
this.a = 1
this.b = 2
}
let o = new f()
// 在f函数的原型上定义属性
f.prototype.b = 3
f.prototype.c = 4
//整个原型链如下:
// {a:1, b:2} ---> {b:3, c:4} ---> Object.prototype---> null
console.log(o.a); // 1
// a是o的自身属性吗?是的,该属性的值为 1
console.log(o.b); // 2
// b是o的自身属性吗?是的,该属性的值为 2
// 原型上也有一个'b'属性,但是它不会被访问到。
// 这种情况被称为"属性遮蔽 (property shadowing)"
console.log(o.c); // 4
// c是o的自身属性吗?不是,那看看它的原型上有没有
// c是o.[[Prototype]]的属性吗?是的,该属性的值为 4
console.log(o.d); // undefined
// d 是 o 的自身属性吗?不是,那看看它的原型上有没有
// d 是 o.[[Prototype]] 的属性吗?不是,那看看它的原型上有没有
// o.[[Prototype]].[[Prototype]] 为 null,停止搜索
// 找不到 d 属性,返回 undefined获取数组中数字的最大最小值:
1
2
3
4
5
6
7
8
9let array = [1,2,3,4,5,6,7]
function maxNumber(arr){
return Math.max.apply(null, arr)
}
function minNumber(arr){
return Math.min.apply(null, arr)
}
maxNumber(array)
minNumber(array)