源码思维
健壮性
代码在发生预期之外的错误时,其应对错误的能力:即就算出错也能够轻松定位到错误,且减少错误的影响范围。
1 | //1、不要轻易去相信传入参数,需要判断参数类型 |
defineProperty
主要用于vue的数据绑定,
使用defineProperty中的get来进行设置属性时,这个属性不能被改值,因为只写了get,只能够取到值而不能改值;要能够改值则需要写上set。其实这是一种变量权限的问题,如果该变量是某个属性的话,则可以使用defineProperty来控制其各类权限。
1 | this.$router = this._root._router; |
模块支持检测:先判断当前的环境符合的哪种模块规范;cmd、amd、umd,或者CommonJS规范、import规范。
架构模式
工厂模式
通俗而讲:我去构建一个工厂方法,让使用者调用这个工厂方法去拿到他要的对象,而不是自己去构建,即不需要去new。
典型例子:jquery。使用jquery时是DOM时代,频繁获取并操作DOM。工厂模式直接用$()就可以拿到对象。
1 | //jQuery |
建造者模式
在构建一个庞大的框架时,先把整个框架分开成几个模块,=》预制=》然后将各个模块融合在一起。
典型例子:vue-2,构建一个庞大的框架。
1 | function Vue(options) { |
函数式
整体的功能就是一大堆的函数,通过函数之间的相互调用来实现整体的功能。对于javaScript,函数才是一等公民:1、tree-shaking:基于文档流的原理,判断某个函数是否被调用,因此能够webpack时自动删除未被调用的函数。2、组合大于继承。因此函数式编程适用于工具库。
典型例子:Vue3,
设计模式
vue-router、vuex这样的只能有一个,即典型的一个类只有一个实例化对象,即单例模式。实现很容易,就是先判断是否已经被实例化过,如果已经实例化过,就不再实例化;需要通过一个变量判断是否已经实例化过。
1 | var _vue; |
代码简洁技巧:jquery中的extend({})方法,传入两个对象时,会将两个对象合并再传入。享元模式:减少重复的代码块的数量,将不同点提取出来作为参数。
1 | function () { |
优雅利用原生方法:vue使用defineProperty来实现双向绑定,但只能应用于对象的属性;那么数组怎么来触发更新?将数组原生的push、pop、shift方法加上了能够触发双向绑定的功能。
1 | let arr = ["push", "pop"]; |
应用进阶
缓存架构-API
优化方案:快、小、省。
缓存:是所有优化方案里最常用、最有效、可以节省http请求,可以从内存中最快读取数据。
1、选择更快的API、算法,减少时间复杂度;
2、看到网站主要消耗的时间,更多地并不在于代码的执行速度,而在于资源加载的速度,因此文件体积小更重要。一、用webpack压缩treeshaking;二、减少代码重复;
vue3方面的改进:1、快:更快的API,用proxy来代替defineProperty;代理proxy不会去改变原对象;diff算法方面改进:对比新老的DOM,先分析动态DOM,只比对动态的DOM;2、小:函数式API:拥抱tree-shaking,可以很方便地将没有用到的方法取出来,并不附加在工程文件中。
3、省:节省http请求
读取数据的快慢:最慢:网络请求;其次:从硬盘中拿数据;最快:从内存中拿数据。因此请求缓存思路就是:有缓存的话,不去发送请求而是直接从缓存中拿去数据。
缓存架构的技巧:
1、缓存架构需要使用单例模式,即所有的缓存都放在一个里面。
2、权限问题,存缓的区域不能直接拿出去给别人操作。因此,需要隐藏起来,使用匿名自执行函数来进行;但同样,需要外界能够进行读取缓存操作,因此需要返回一个对象,在该对象内有一系列操作缓存的方法。这其实是函数闭包的应用。
3、缓存都会存在副作用:
一、更新问题:使用localstorage、session、cookies缓存时,缓存至本地,需要考虑更新问题。(1)、与后端进行websocket连接,但过于麻烦,没必要;(2)、通过定期轮询,定时器,每隔一段时间向后端发起ajax请求;经常变动的API不要用这种缓存;
使用内存缓存时,是不用考虑更新问题;但内存缓存同样有自己的问题,需要考虑占用内存问题,每往里面加东西,都会占用内存。javascript的内存限制较严重,因此需要做一个限制。
1 | if (!window.mycache) { |
vue插件
关键的两个API:Vue.use;Vue.mixin。
Vue.use();原理:将一个方法执行一次,如果该方法中有install属性,就执行其install属性,来代替执行该方法;
Vue.mixin();原理:相当于一个全局混合;(局部混合相当于在组件的export后写mixin),可以混合方法methods、数据data、混合生命周期(生命周期的混入才是核心功能)。即,混入的生命周期操作,所有的组件在对应的生命周期均执行该操作函数。
打包项目=》打包体积过大,可以使用异步加载来减少体积 =》 vuex内容太大;=》vuex异步加载,根据组件来异步加载vuex,放在beforeCreated阶段,在DOM还没有加载好之前,将其之间的依赖关系读取好。
插件的用途:1、提供逻辑复用;2、注入自定义操作;
常用API
Vue.util.defineReative:其实就是Vue自身去做响应式的方法,;一般来说只有data的数据能触发响应。这里,我们可以调用这个API,使外部数据也能触发响应。
用法:1、将localstorage中的数据触发响应,不需要将其取出来;2、监听window的事件,常用的是resize,实现尺寸的自适应;3、监听浏览器版本、内存;
本质是让外部数据也能触发响应。
Vue.extend:传入一个对象时,其会返回一个构造函数,直接new便可以创建实例。用于import,在使用import时,导入的是vue的选项。
vue单元测试=》测某个组件的方法和节点渲染结果
render渲染:提供函数,用JS来表达你的整个template,当页面的逻辑较为复杂时。
API层
Axios源码分析
Axios如何实现请求拦截、响应拦截
1、初始化Axios,其实是调用request方法;
请求拦截器设置的处理——发送请求——响应拦截器设置的处理:这些一大堆方法由数组来存储;
1 | axios.interceptors.request.use(()=> { |