技术亮点:
组件封装
插件二次封装
带团队---整个项目流程把控
团队代码保障
Cr
双向数据绑定原理
vue实现对数据的双向绑定,通过对数据劫持结合发布者-订阅者模式实现的。
vue通过Object.defineProperty来实现数据劫持,会对数据对象每个属性添加对应的get和set方法,对数据进行读取和赋值操作就分别调用get和set方法。
实现双向数据绑定,首先要对数据进行数据监听,需要一个监听器Observer,监听所有属性。如果属性发生变化,会调用setter和getter,再去告诉订阅者Watcher是否需要更新。由于订阅者有很多个,我们需要一个消息订阅器Dep来专门收集这些订阅者,然后在监听器Observer和订阅者Watcher之间进行统一管理。还有,我们需要一个指令解析器Complie,对每个元素进行扫描和解析,将相关指令对应初始化成一个订阅者Watcher,并替换模板数据或绑定相应函数。当订阅者Watcher接收到相应属性的变化,就会执行对应的更新函数,从而更新视图。
1,v-modal实现原理
其实v-model是vue的一个语法糖。即利用v-model绑定数据后,既绑定了数据,又添加了一个input事件监听。
实现原理:
1、v-bind绑定响应数据
2、触发input事件并传递数据
<input v-model="text"></input>
// 等价于:
<input :value="text" @input="text = $event.target.value"></input>
// 组件中使用:
<custom-input :value="text" @input="$event"></custom-input>
// 根据v-model原理模拟:
<input type="text" id="ipt1">
<input type="text" id="ipt2">
<script>
var ipt1=document.getElementById('ipt1');
var ipt2=document.getElementById('ipt2');
ipt1.addEventListener("input",function(){
ipt2.value=ipt1.value;
})
</script>
2,data为啥是函数
因为组件是用来复用的,且 JS 里对象是引用关系,如果组件中 data 是一个对象,那么这样作用域没有隔离,子组件中的 data 属性值会相互影响,
如果组件中 data 选项是一个函数,那么每个实例可以维护一份被返回对象的独立的拷贝,组件实例之间的 data 属性值不会互相影响;
3,.async原理
它只是作为一个编译时的语法糖存在。它会被扩展为一个自动更新父组件属性的 v-on 监听器。
可代替 子组件 调用 父组件 传过来的方法实现子传父
//父组件将age传给子组件并使用.sync修饰符。
<MyFooter :age.sync="age">
</MyFooter>
//子组件触发事件
mounted () {
console.log(this.$emit('update:age',1234567));
}
注意事件名前缀必须是 update
4,函数柯里化
实际上当你了解了后才发现其实就是高阶函数的一个特殊用法
是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数而且返回结果的新函数的技术。
好处
1. 参数复用(正则示例)
2. 提前确认
5,防抖和节流
防抖(debounce)
所谓防抖,就是指触发事件后在 n 秒内函数只能执行一次,如果在 n 秒内又触发了事件,则会重新计算函数执行时间。
function debounce(fn,delay){
let timer = null //借助闭包
return function() {
if(timer){
clearTimeout(timer)
}
timer = setTimeout(fn,delay) // 简化写法
}
}
节流(throttle)
所谓节流,就是指连续触发事件但是在 n 秒中只执行一次函数。
function throttle(fn,delay){
let valid = true
return function() {
if(!valid){
//休息时间 暂不接客
return false
}
// 工作时间,执行函数并且在间隔期内把状态位设为无效
valid = false
setTimeout(() => {
fn()
valid = true;
}, delay)
}
}
/* 请注意,节流函数并不止上面这种实现方案,
例如可以完全不借助setTimeout,可以把状态位换成时间戳,然后利用时间戳差值是否大于指定间隔时间来做判定。
也可以直接将setTimeout的返回的标记当做判断条件-判断当前定时器是否存在,如果存在表示还在冷却,并且在执行fn之后消除定时器表示激活,原理都一样
*/
5,作用域(链)是在什么时候建立的
定义的时候就创建了 (红宝书)
整个解释过程是这样的: 页面加载; 创建window全局对象,并生成全局作用域; 然后生成执行上下文,预解析变量(变量提升),生成全局变量对象; 然后逐行解析,执行流依次执行每行/块代码;
在创建变量对象的过程中沿定义域链逐级线上搜索变量
6,函数调用方式有哪些
- 函数模式:普通调用 this指向全局对象window
- 方法模式:方法一定是依附于一个对象, 将函数赋值给对象的一个属性, 那么就成为了方法.this指向调用他的对象
- 构造器模式
- 上下文模式
- call,apply都是执行某一函数,发现this有变得时候才使用的(进行时)
- bind是在函数进行调用之前,就强行给变了this的指向(进行前),它的效果是返回一个函数(只是给变了this指向)
7,路由守卫
全局路由守卫:router.beforeEach
全局后置钩子:router.afterEach
路由独享守卫:beforeEnter
组件内的守卫:
beforeRouteEnter
beforeRouteUpdate
(2.2 新增)beforeRouteLeave
对NodeJS模块机制的理解
1. Commonjs模块规范
1.1 模块引用
原理:这里其实就是包装了一层立即执行函数,这样就不会污染全局变量了
var math = require('math');