1.Vue自定义指令懒加载
钩子函数
bind: 只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置。
inserted: 被绑定元素插入父节点时调用 (仅保证父节点存在,但不一定已被插入文档中)。
update: 所在组件的 VNode 更新时调用,但是可能发生在其子 VNode 更新之前。指令的值可能发生了改变,也可能没有。但是你可以通过比较更新前后的值来忽略不必要的模板更新
componentUpdated: 指令所在组件的 VNode 及其子 VNode 全部更新后调用。
unbind: 只调用一次,指令与元素解绑时调用。
钩子函数参数
指令钩的函数会被传入以下参数:
el:指令所绑定的元素,可以用来直接操作 DOM。
binding:一个对象,包含以下 property:
name:指令名,不包括 v- 前缀。
value:指令的绑定值,例如:v-my-directive="1 + 1" 中,绑定值为 2。
oldValue:指令绑定的前一个值,仅在 update 和 componentUpdated 钩子中可用。无论值是否改变都可用。
expression:字符串形式的指令表达式。例如 v-my-directive="1 + 1" 中,表达式为 "1 + 1"。
arg:传给指令的参数,可选。例如 v-my-directive:foo 中,参数为 "foo"。
modifiers:一个包含修饰符的对象。例如:v-my-directive.foo.bar 中,修饰符对象为 { foo: true, bar: true }。
vnode:Vue 编译生成的虚拟节点。
oldVnode:上一个虚拟节点,仅在 update 和 componentUpdated 钩子中可用。
2.深拷贝,考虑正则,Date这种类型的数据
function deepClone(obj, hash = new WeakMap) {
if (obj instanceof RegExp) {
return new RegExp(obj)
}
if (obj instanceof Date) {
return new Date(obj)
}
if (obj == null || typeof obj !== 'object') {
return obj
}
if (hash.has(obj)) {
return hash.get(obj)
}
let a = new obj.constructor()
hash.set(obj, a)
for (let key in obj) {
//递归
if (obj.hasOwnProperty(key)) {
a[key] = deepClone(obj[key], hash)
}
}
return a
}
var show = {
name: '小明',
fn: function () { console.log(1) },
age: null,
pic: undefined,
}
var show2 = deepClone(show)
show2.name = "Mary"
console.log(show, show2)
3.实现Promise.all, Promise.allSettled
该Promise.allSettled()方法返回一个在所有给定的promise都已经fulfilled或rejected后的promise,并带有一个对象数组,每个对象表示对应的promise结果。
当您有多个彼此不依赖的异步任务成功完成时,或者您总是想知道每个promise的结果时,通常使用它。
相比之下,Promise.all() 更适合彼此相互依赖或者在其中任何一个reject时立即结束。
4.手写节流/防抖
//函数防抖
function debounce(fn, wait, immediate) {
let timer = null;
// 返回一个函数
return function(...args) {
// 每次触发事件时都取消之前的定时器
clearTimeout(timer);
// 判断是否要立即执行一次
if(immediate && !timer) {
fn.apply(this, args);
}
// setTimeout中使用箭头函数,就是让 this指向 返回的该闭包函数,而不是 debounce函数的调用者
timer = setTimeout(() => {
fn.apply(this, args)
}, wait)
}
}
//函数节流
function throttle(fn, wait) {
// 记录上一次执行的时间戳
let previous = 0;
// 设置一个定时器
let timer = null;
return function(...args) {
// 当前的时间戳,然后减去之前的时间戳,大于设置的时间间隔
if(Date.now() - previous > wait) {
clearTimeout(timer);
timer = null
// 更新上一次的时间戳为当前时间戳
previous = Date.now();
fn.apply(this, args);
} else if(!timer) {
// 设置下一个定时器
timer = setTimeout(() => {
timer = null;
fn.apply(this, args)
}, wait)
}
}
}
5.实现一个vue的双向绑定
const obj = {
name: 'app',
age: '18',
a: {
b: 1,
c: 2,
},
}
const p = new Proxy(obj, {
get(target, propKey, receiver) {
console.log('你访问了' + propKey);
return Reflect.get(target, propKey, receiver);
},
set(target, propKey, value, receiver) {
console.log('你设置了' + propKey);
console.log('新的' + propKey + '=' + value);
Reflect.set(target, propKey, value, receiver);
}
});
p.age = '20';
console.log(p.age);
p.newPropKey = '新属性';
console.log(p.newPropKey);```
**6.vue.js的两个核心是什么?**
```javascript
1、数据驱动,也叫双向数据绑定。
Vue.js数据观测原理在技术实现上,利用的是ES5Object.defineProperty和存储器属性: getter和setter(所以只兼容IE9及以上版本),可称为基于依赖收集的观测机制。核心是VM,即ViewModel,保证数据和视图的一致性。
2、组件系统。
.vue组件的核心选项:
1、模板(template):模板声明了数据和最终展现给用户的DOM之间的映射关系。
2、初始数据(data):一个组件的初始数据状态。对于可复用的组件来说,这通常是私有的状态。
3、接受的外部参数(props):组件之间通过参数来进行数据的传递和共享。
4、方法(methods):对数据的改动操作一般都在组件的方法内进行。
5、生命周期钩子函数(lifecycle hooks):一个组件会触发多个生命周期钩子函数,最新2.0版本对于生命周期函数名称改动很大。
6、私有资源(assets):Vue.js当中将用户自定义的指令、过滤器、组件等统称为资源。一个组件可以声明自己的私有资源。私有资源只有该组件和它的子组件可以调用。
等等。
6.什么是vue生命周期?
Vue实例有一个完整的生命周期,也就是从开始创建、初始化数据、编译模板、挂载Dom、渲染→更新→渲染、销毁等一系列过程,我们称这是Vue的生命周期。通俗说就是Vue实例从创建到销毁的过程,就是生命周期。
7.第一次页面加载会触发哪几个钩子?
第一次加载会触发 beforeCreate、created、beforeMount、mounted
8.说一下你对axios的理解?
什么是axios?
Axios 是一个基于 promise 的 HTTP 库,简单的讲就是可以发送get、post请求。
axios一般什么时候用?
在特性里面已经有提到,浏览器发送请求,或者Node.js发送请求都可以用到Axios。像Vue、React、Node等项目就可以使用Axios
9.原型与原型链
原型链:当访问一个对象的某个属性时,会在当前对象本身进行查找,如果没有找到,则会去它的__proto__隐式原型上查找,也就是构造函数的prototype,如果还没找到就会在构造函数的prototype的__proto__中查找
原型:这是每个对象(除null外)都会有的属性,叫做__proto__,这个属性会指向该对象的原型。
10.继承的几种方式
//原型链继承
function Fu() {
this.age = 19
}
Fu.prototype.say = function () {
return this.age
}
function Zi() {
this.age = 22
}
Zi.prototype = new Fu()
Zi.prototype.say = function () {
return this.age
}
Zi.prototype.constructor = Zi
let obj = new Zi()
console.log(obj.say())
// 构造函数
function Fu(name){
this.name=name
this.color=['pink','blue','black']
}
function Zi(name){
Fu.call(this,name)
}
let obj=new Zi('orange')
obj.color.push('green')
console.log(obj.color)
//组合继承
function Fu(name){
this.color=['pink','blue','black']
this.name=name
}
Fu.prototype.say=function(){
console.log(this.name)
}
function Zi(name,age){
this.age=age
Fu.call(this,name)
}
Zi.prototype=new Fu()
Zi.prototype.constructor=Zi
Zi.prototype.sayage=function(){
console.log(this.age)
}
let obj=new Zi('asd',20)
obj.color.push('yellow')
console.log(obj.color)
obj.say()
obj.sayage()
//寄生组合继承
//寄生式继承