vue源码调试
前言最近在熟悉关于vue的公共api的时候,有时真的怀疑关于这个api方法是否真的是这样子执行,执行顺序是怎样的,为什么是这样子的逻辑。带着问题来解读代码,但需要深入到代码中才能够了解到具体的程序执行逻辑。
工欲善其事必先利其器,这里就需要对源码进行调试,那么应当如何进行源码的调试呢?
配置步骤一、配置文件入口添加source-map
二、执行命令:npm run dev将在dist目录中生成对应的vue.js文件
三、添加调试网页,直接采用cdn方式来使用
四、在浏览器中访问页面,通过在vue源码代码中添加debugger直接加入断点
Object.defineProperty重新捡起学习
前言🤔 一般的,我们定义一个对象的属性的时候,可以简单的通过对象字面量来定义并声明对象的属性,如下:
var obj = { a : 123 };
定义了一个obj对象,其属性a的值赋为123。既然JavaScript中已经提供了这种方式来声明定义对象以及其属性,为啥子还要多此一举来提供Object.defineProperty这个静态API来给对象定义属性呢??
✨ 首先,对于Object.defineProperty()的定义是:直接在一个对象上定义一个新的属性,或者修改一个对象的现有属性,并返回此对象。这里在定义属性的同时,不单单提供属性的值,还提供了属性的数据操作+数据属性描述,该方法允许精确地添加或修改对象的属性,一般通过简单的赋值操作,其属性描述符中的属性都是true的。
var obj = {};Object.defineProperty(obj, ‘a’, { value: 123, writable: ‘boolean,当且仅当该值为true的时候,普通的.属性操作符或者[]属性操作符才可以对a属性进行赋值’, enumerable: ‘boolean, ...
每天一设计模式-享元模式
前言
享元模式主要用于减少创建对象的数量,以减少内存占用和提高性能,通过运用共享技术有效地支持大量的细粒度的对象,避免对象间拥有相同内容造成多余的开销.这种模式尝试重用现有的同类对象,如果未找到匹配的对象,则创建新对象。
意图:运用共享技术有效地支持大量细粒度的对象;
主要解决:在有大量对象时,有可能会造成内存溢出,我们把其中公共的部分给抽象出来,如果有相同的业务请求,直接返回在内存中已有的对象,避免重新创建对象;
何时使用:
系统中有大量的对象时,有可能会造成内存溢出;
这些对象大量消耗内存;
这些对象的状态大部分可以外部化(通过外部传递数据直接完成功能的实现);
这些对象可以按照内蕴状态分为很多组,当把外蕴对象从对象中剔除出来时,每一组对象都可以用一个对象来代替;
系统不依赖于这些对象身份。
如何使用:用唯一标识码判断,如果在内存中有,则返回这个唯一标识码所标识的对象
应用实例:
Java中的String,如果有则直接返回,如果没有则创建一个字符串保存在字符串缓存池里面;
数据库中的连接池
注意事项:
注意划分外部状态和内部状态,否则有可能引起线程安全;
这些类必须有一 ...
Vue中的静态方法
前言
Vue中提供了以下几个全局API,供我们来使用,这边做了对应的整理:
部分静态方法专题介绍官方上的针对各个静态方法已做了比较详细的解释,这边仅针对其中的一两个进行延伸学习
Vue.observable
让一个对象可响应。Vue内部会用它来处理data函数返回的对象。返回的对象可以直接用于渲染函数和计算属性内,并且会在发生变更时触发相应的更新。也可以作为最小化的跨组件状态存储器,用于简单的场景。⚠️ 在Vue2.x中,被传入的对象会直接被Vue.observable变更,但其实是属于同一个对象。
🤔 Vue最独特的特性之一,就是其非侵入性的响应式系统,我们普通传递给到组件中的data函数中返回的对象,仅仅是一个普通的js对象而已吖,为什么当我们修改它的值的时候,对应的页面会发生改变,以及对应的声明周期钩子函数也会发生对应的调整,这个是怎样的一个状态管理机制的呢?
✨ **关于这个机制的实现,采用的是Object.defineProperty**,通过对该静态方法的一个使用,可以对原有对象的属性在发生set赋值操作的时候,额外调用其他逻辑操作,来满足这个架构的功能实现,通过O ...
每天一设计模式-适配器模式
前言
组合模式,又叫部分-整体模式,将对象组合成树形结构一表示”部分整体”的层次结构。该模式创建了一个包含自己对象的类,该类提供了修改相同对象组的方式,使得用户对单个对象和组合对象的使用具有一致性。
意图:将对象组合成树形结构以表示”部分-整体”的层次结构,使得用户对单个对象和组合对象的使用具有一致性;
主要解决:它在树形结构的问题中,模糊了简单元素和复杂元素的概念,客户程序可以像处理简单元素一样来处理复杂元素,从而使得客户程序与复杂元素的内部结构解耦;
何时使用:
想表示对象的部分-整体层次结构(树形结构);
希望用户忽略组合对象与单个对象的不同,用户将统一地使用组合结构中的所有对象
如何实现:树枝和叶子统一接口,树枝内部组合该接口
关键代码:树枝内部组合该接口,并且含有内部树形List,里面放Component
优点:
高层模块调用简单;
节点自由增加
缺点:在使用组合模式时,其叶子和树枝的声明都是实现类,而不是接口,违反了依赖倒置原则
使用场景:部分、整体场景,如树形菜单,文件、文件夹的管理。
代码实现
想要实现一个Form表单的表单元素自由组合创建
12345678 ...
Vue函数式组件的学习与运用
前言
函数式组件一般比较简单,没有任何的管理状态,也没有监听任何传递给它的状态,也没有生命周期方法,实际上,它仅仅是接受一些prop的函数,在这样的场景下,我们可以将组件标记为functional,这意味着它将无状态(没有响应式数据),也没有实例上下文。
函数式组件的定义与使用
官方提供了两种方式来定义函数式组件
函数式组件的定义1、纯代码方式定义12345678910111213141516171819 Vue.component('my-functional-component', { functional: true, props: { // 传递进来的参数 xxx: { type: Object, default: null } }, render(h, context){ // context为传递进来的上下文 } });// 或者我们可以直接是以👇的一个单JS文件来定义,然后再在具体的页面/组件中来使用,个人一般使用以下的方式来创建自己的一个函数式组件export d ...
每天一设计模式-代理模式
前言
由于一个对象不能直接引用另外一个对象,所以需要通过代理对象在这两个对象之间起到一个中介的作用。在代理模式中,我们通过创建具有现有对象的对象,以便于向外界提供功能功能接口。
意图:为其他对象提供一种代理以控制对这个对象的访问。
主要解决:在直接访问对象时带来的问题,比如说:要访问的对象在远程的机器上。在面向对象系统中,有些对象由于某些原因(比如对象创建开销很大,或者某些操作需要安全控制,或者需要进程外的访问),直接访问会给使用者或者系统结构带来很多麻烦,我们可以在访问此对象时加上一个对此对象的访问层。
何时使用:想在访问一个类时做一些控制。
如何解决:增加中间层。
关键代码:实现与被代理类组合。
ES5代码实现123<div id="imgContainer"> <img id="realImg" style="width: 80px; height: 80px;"></div>
12345var tempImg = new Image();tempImg.src = 'https://www.91temaichang.com/2022/03 ...
每天一设计模式-适配器模式
前言
适配器模式(Adapter Pattern)是作为两个不兼容的接口之间的桥梁,它结合了两个独立接口的功能,这种模式设计到一个单一的类,该类负责加入独立的或者不兼容的接口功能。将一个类(对象)的接口(方法/属性)转换成为另外一个接口,以满足用户需求,使类(对象)之间接口的不兼容问题通过适配器得以解决。🤔这其实是日常业务开发过程中经常出现到的一个问题,为了兼容到不同业务系统不同接口的不同实现方法方案,所进行的适配工作。
意图:将一个类的接口转换成客户希望的另外一个接口。适配器模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。
主要解决:主要解决在软件系统中,常常要将一些”现存的对象”放到新的环境中,而新环境要求的接口是现对象不能满足的。
何时使用: 1、系统需要使用现有的类,而此类的接口不符合系统的需要。 2、想要建立一个可以重复使用的类,用于与一些彼此之间没有太大关联的一些类,包括一些可能在将来引进的类一起工作,这些源类不一定有一致的接口。 3、通过接口转换,将一个类插入另一个类系中。(比如老虎和飞禽,现在多了一个飞虎,在不增加实体的需求下,增加一个适配器,在里面包 ...
每天一设计模式-外观模式
前言
隐藏系统的复杂性,并向客户端提供一个客户端可以访问系统的接口,通过这个接口使得对子系统接口的访问更加容易,提供对客户端系统的简化方法和现有系统类方法的委托调用。其实也是属于面向对象编程中的一种编程思维模式:针对接口编程,在面对不同的复杂对象,仅需要将复杂对象对外提供统一的简单明确调用的业务方法,然后自身隐藏复杂逻辑其中,调用者无须关心内部具体实现业务逻辑
意图:为子系统中的一组接口提供一个一致的界面,外观模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。
主要解决:降低访问复杂系统的内部子系统时的复杂度,简化客户端之间的接口。
何时使用: 1、客户端不需要知道系统内部的复杂联系,整个系统只需提供一个”接待员”即可。 2、定义系统的入口。
如何解决:客户端不与系统耦合,外观类与系统耦合。
关键代码:在客户端和复杂系统之间再加一层,这一层将调用顺序、依赖关系等处理好。
ES5代码实现1234567891011121314151617 var A = {g: function(id) { return document.getElementById(id);},css: ...
每天一设计模式-单例模式
前言
单例模式(Singleton Pattern)属于创建型模式,它提供了一种创建对象的最佳方式,涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个该类对象被创建,提供了一种访问其唯一的对象的方式,可以直接访问,一般不需要实力话该类的对象
⚠️ 有以下几个点需要注意:
单例类只能有一个实例;
单例类必须自己创建自己的唯一实例;
单例类必须给所有其他对象提供这一实例。
✨ 模式具体介绍:意图:保证一个类仅有一个实例,并提供一个访问它的全局访问入口;主要解决:一个全局使用的类频繁地创建于销毁;何时使用:当我们需要控制实例的树木,节省系统资源的时候;如何解决:判断系统是否已经有这个单例,如果有则返回,如果没有则创建;关键代码:真正实例是私有的,无法直接方法的
ES5代码实现123456789101112131415161718// LazySingle.jsvar LazySingle = (function() { // 全局共享的实例 var _instance = null; function Single(){ return { xx: fun ...
从新开始认识JavaScript原型
前言一切,从以下的两行代码开始说起
12function Foo() {}var foo = new Foo();
✨ 面向对象编程是一种程序设计范式,它将对象作为程序的基本单元,将程序和数据封装📦其中,以提高程序的重用性、灵活性和扩展性。
上面定义了一函数对象Foo,并利用该构造函数,创建了一个foo实例,该实例对象指向的是Foo
Object对象Object是JavaScript中的一种数据类型,用来存储各种键值对集合和更加复杂的实体,Object可以通过Object()构造函数或者直接使用对象字面量的方式来创建。在JavaScript中,几乎所有的对象都是Object类型的实例,它们都会从Object.prototype中继承属性和方法,虽然一部分属性/方法会被重写。
🤔 这里有一个疑问,为什么自定义创建出来的对象,默认就拥有了Object实例中的方法?👉 首先所有的对象都是Object类的实例对象,它们会从Object.prototype中继承属性和方法,而且,每一个实例对象中都拥有一个属性**proto**,该属性代表在实例化一个对象的时候,将会使用__proto_ ...
每天一设计模式-建造者模式
前言
原型模式用于创建重复的对象,使用于创建新的对象的类共享资源对象的属性以及方法。在JavaScript中,则是基于原型链实现对象之间的继承,这种继承是基于一种对方法/属性的共享,而不是对方法/属性的复制。除非是new来设置子类的原型指向将可复用的、可共享的、耗时久的动作从基类中提取出来,然后放到对应的原型中,然后子类通过组合继承或者寄生组合继承的方式将方法继承下来,对于子类中那些需要重写的方法则进行直接的重写,这样子子类则共享了父类中的原型方法
ES5代码1234567891011121314151617181920212223242526 function LoopImages(imgArr, container){this.imageArray = imgArr;this.container = container; } LoopImages.prototype = {createImage: function() { console.info('LoopImages createImages function' + this.imageArray);},changeIma ...
每天一设计模式-抽象工厂模式
前言通过对类的工厂抽象使其业务用于对产品类簇的创建,而不仅仅局限于创建某一类产品的实例子。
围绕一个超级工厂来创建其他的工厂,该超级工厂又成为其他工厂的工厂,负责创建一个相关对象的厂(该厂用于创建某一类产品),每个生成的工行都按照工厂模式去创建各自的对象。
ES5代码⚠️ 由于JavaScript中并不支持抽象类的方式,没有像Java中的abstract关键词来修饰类以及方法,因此这边采取了一种投机取巧的方式,就是将需要被定义为abstract的方法直接抛出一个异常,代表不能直接调用其方法。
123456789// VehicleFactory.js 抽象工厂方法// 这里subType假定是BMW,superType假定是Carvar VehicleFactory = function(subType, superType) { function F() {} F.prototype = new superType(); // 这里采用构造调用,这里以👇的Car为例子,使得F的prototype拥有了实际的getPrice + getSpeed方法,但需要注意的是通过这种 ...
每天一设计模式-建造者模式
前言
将一个复杂对象的构建层与表示层互相分离,同样的构建过程可采用不同的表示。虽然建造者模式也是为了创建一个对象,但该模式更专注与对象的一个创建过程,而之前所习🉐️的工厂类模式则专注于结果,更关注是创建对象的细节通过将对象的不同组成部分,交由每个不同的对象来实现,也可以说这种模式所创建出来的对象是一个复合对象⚠️ 这种方式在无形中会增加对象的复杂性,因此如果对象的颗粒度很小的话,或者模块之间的复用率很低并且变动不大的话,优先采用创建一整个对象。
意图: 将一个复杂的构建与其表示分离,使得同样的构建过程可以创建不同的表示主要解决: 主要解决在软件系统中,有时候面临一个”复杂对象”的创建工作,其通常由各个部分的子对象用一定的算法构成;由于需求的变化,这个复杂对象的各个部分经常面临剧烈变化,但将他们组合在一起的算法却相对稳定何时使用: 一些基本不见不会变,而其组合经常变化的时候应用实例: 去M记,汉堡、可乐、薯条、炸鸡等基本不变,而其组合是经常变化的,从而生成出所谓的”套餐”
ES5代码1234567891011 // Picture.js 抽象图片信息类,包含卡片信息、组合方式信息 f ...
每天一设计模式-工厂方法模式
前言工厂方法模式是通过对产品类的抽象使其创建业务主要负责用于创建多类产品的实例,按照之前的介绍,如果随着业务的开展,需求不断的增加,假如使用简单工厂模式,那么我们需要添加对应的类,以及在工厂函数中新增对应的case分支代码,来创建对应的实例。将原本的工厂方法,当作一个类对象,需要新增的需求,都只需要通过在该类中的不同属性来对应创建不同的实例对象即可,且不同的实例对象它们之间共享着由工厂方法提供的共同属性。⚠️ 由于是工厂方法,有可能在使用过程中,不小心当作普通的方法来调用了,因此可以采取将方法保护起来的方式
安全的方法工厂类123456789var Factory = function(type, content) { if(this instanceof Factory){ // 正常使用了new关键词来调用Factory方法对象 return this[type](content); }else{ // 若不是正常 return new Factory(type, content); }}
ES5代码1234567891011121314151617 ...
Vue指令学习与实际应用场景
前言
在Vue2.0中,代码复用和抽象的主要形式是组件,然而,有时候需要对普通DOM元素进行底层操作,这个时候就可以使用自定义指令,来满足业务诉求。
指令钩子函数和参数说明
如何使用指令
自定义指令需要使用,则必须先注册,Vue自定义指令,可以有局部注册和全局注册两种方式,
全局注册:Vue.directive(id, [definition]),然后在入口文件中调用Vue.use()
局部注册:在对应的*.vue组件文件中的directive属性中编写
✨ 一般情况下,需要使用到指令说明是需要全局公用的,不然就没有太多的必要来定义这个指令了,而且一般这个指令可以有多个,这边可以是编写一个统一的入口文件,实现指令的一个批量注册,以便于后续直接使用,比如有以下的一个入口文件:
123456789101112import copy from './modules/copy';import longpress from './modules/longpress';const directives = { copy, longpress};export default { inst ...
每天一设计模式-简单工厂模式
前言简单工厂模式(Simple Factory),又叫静态工厂方法,由一个工厂方法决定创建某一种产品对象类的实例,主要用来创建同一类对象。使用者无须知道这些对象的一个依赖关系,而仅仅需要知道关于这个工厂方法即可。一般🈶️两种方式:
通过类实例化对象来创建
通过创建一个新对象,然后包装增强其属性和功能来实现的
两种方式所造成的不同点在是否做到了将公共部分进行抽离的目的。
ES5代码以下主要提供两种简单工厂模式来创建不同的对象
方式一1234567891011121314151617181920212223242526272829303132 var Basketball = function() { this.intro = '我是篮球'; } Basketball.prototype = {getNum: function (){ console.info('每只球队需要5人参赛');},getBallWeight: function() { console.info('篮球很重');} }; var Football = function() { this.intr ...
理解JavaScript中的封装与继承
前言面向对象编程是一种程序设计范型,它将对象作为程序的基本单元,将方法和数据封装其中,以提高程序的重用性、灵活性和扩展性。想要通过学习JavaScript设计模式,让自己的代码在满足正常业务迭代的前提下,让自己的代码更加富有灵活性,享受编写代码的乐趣,而不是枯燥无味地来完成工作任务,从而来提升自身的一个编码水平。
JavaScript中的函数是一等对象
var foo = function(){}typeof foo; // object
从上述可知,函数也是一对象,它与普通的object对象的区别在于它是可执行的,我们知道,对象可定义属性,属性可以是数据,也可以是方法,通过函数将属性与方法实现隐藏其中,对外暴露api的方式,即可达到面向对象编程的基本思维。
✨ 函数一般只能被调用,但是如果我们的函数返回的是一个对象,而该对象又封装了一些函数以及属性的话,那么我们可以利用该对象来赋予对应的操作,对应的示例代码如下:
1234567891011 function Foo(){return { x: 123, y: 456, fun: function(content){ ...
JavaScript中的浏览器学习(存储篇)
前言
WEB应用允许使用浏览器客户端所提供的API,将网页应用所需的数据存储到浏览器客户端,按照不同的源进行各自维护,也就是不同源域名下的数据各自分离,各自管理,从而使得网页应用能够”记住”上一次所做的一些操作,提升用户体验,完善业务闭环,目前较为常见的浏览器存储方式有:
WEB存储(localStorage + sessionStorage)
Cookie
离线WEB应用(已废弃)
WEB数据库(indexdb)
文件系统
一、storage存储(localStorage + sessionStorage)
在window对象中定义了两个只读属性:localStorage + sessionStorage,两者在使用上并无太大的区别,只是在于浏览器存储的时间有效期和作用于的区别🤔区别:localStorage存储的数据,是永久性存储的,只要没有显示地修改/删除,就算关闭浏览器,所缓存的数据依旧存在,localStorage是限制在文档源(http协议 + 域名 + 端口号),所存储的内容,都是以字符串形式来存储的,因此如果需要做通用性的api的话,需要将其中的不同类型的val ...
关于申请开通微信支付的文档描述
前言由于需要在目前的区域平台开通微信支付功能,提供给到企业区域平台配置自有收款业务,因此特别整理关于微信小程序/公众号注册、微信支付商户开通指引流程
资料准备上述是需要准备的相关资料,由于需要同时注册公众号/小程序 + 微信商户号,因此,需要同时准备上述资料。
小程序/公众号开通指引1、小程序注册流程,点我查看,若其中流程有使用企业对公打款动作的话,需要在注册成功后,用对应企业的对公银行账号进行打款,有类似以下的一个打款效果图:2、小程序认证申请流程,点我查看,认证过程需要下载一pdf的公函,需要将该pdf给下载下来,然后签名盖章,填写对应的日期,然后将整张图片进行拍照,并在认证流程过程中来提交上传,公函3、提交完成认证信息后,需要进行一次300费用的支付,用对应公函上的实名认证的微信账号进行扫码付款4、以上所有的流程通过后,微信将会安排对应的客服人员进行一次电话回访,对所填写的信息的一个确认,⚠️这里需要需要注意的是需要确保资料都填写无误,若多次填写错误,将导致认知费用无效,🉐️继续重新支付认证的支付费用。
微信支付商户开通指引介绍
微信支付,是微信向有出售物品/提供服务需求的商家 ...