当前位置: 首页 > Web前端 > vue.js

模仿vue自己写一个响应式框架(二)——Vue对象创建

时间:2023-04-01 12:44:51 vue.js

上一章我们使用vue实现了一个简单的todo应用。如果我们去掉vue.js的引用,界面会先显示原文Content然后控制台报错index.html:22UncaughtReferenceError:Vueisnotdefinedatindex.html:22原因是我们创建了Vue对象通过代码中的varapp=newVue({...}),而Vue对象是在vue.js中定义的,现在没有vue.js会报错。本章内容是解决找不到vue对象的问题,让代码不再报错。为什么要先解决js报错的问题而不是文字显示的问题呢?因为Vue对象提供了Vue的所有功能,包括值绑定,解决了值绑定的问题界面自然会恢复正常,所以先解决找不到Vue对象的问题。匿名函数和闭包首先解释一下什么是匿名函数。顾名思义,就是没有定义名称的函数,比如下面的//函数表达式varfn=functionadd(a,b){returna+b;}varc=fn(1,2);//以上例子的组合(function(a,b){returna+b;})(1,2);//事件响应函数varbutton=document.getElementById('submitButton');button.onclick=function(){//dosomething}还有其他情况,这里就不一一列举了。Java也有匿名类,类似于js的匿名函数。下面说说前端面试必问的问题。无数前端同学弯腰的闭包是什么?包这个词没有想象空间,容易引起误解。关闭与包无关。我不精确但直观的理解是闭包就是一个类,你可以理解为java中闭包就是一个类。在java类中,类可以定义变量和方法,方法可以引用类变量。它类似于js和java类。就是js的函数,java类变量就是js函数里面定义的变量,java类的方法就是js函数里面定义的函数。例如:functionCircleArea(r){varPI=3.14159;函数计算(){返回PI*r*r;}returncalculate;}varcircle2=CircleArea(2);vararea=circle2();console.log(area);通常,当函数执行时,变量会被回收。计算函数在函数CircleArea中返回。理论上pi已经被回收了,因为函数已经执行完了,但是当vararea=circle2();在函数外执行,结果还是正确的,说明PI没有被回收。这就是闭包的特点。函数和对其周围状态(词法环境、词法环境)的引用捆绑在一起形成闭包。这是官方的闭包包定义。那么在我们的应用中,Vue是以什么形式存在的,对象还是函数呢?毫无疑问,它一定是一个函数。只有在函数中才能实现复杂的逻辑,实现生命周期控制。所以如果想让varapp=newVue({...})这行代码不报错,一个可行的方案如下:varVue=function(options){console.log(options);}创建一个名为vuex.js的js文件,将上面的代码复制到js文件中,将上一章html中对vue.js的引用改为引用vuex.js,再次运行。虽然界面还是原样输出,但是控制台不再报错了,它也正确打印出数据。本章的目的就达到了。能不能优雅一点?如果你看过jquery源码和vue源码,大家一定能看到开头这样一段代码(function(global,factory){....})(this,function(options){...})的代码。就像上面的匿名函数(function(a,b){returna+b;})(1,2);一样,没错,这是一个立即执行的匿名函数。整个框架的逻辑写在函数里,配置是通过options。传入,这样写有什么好处呢?它更加优雅整洁。拥有独立的运行环境,多个框架之间不会冲突。重要的原因是为了保证独立的运行环境。闭包是通过匿名函数实现的,整个框架的逻辑都在闭包中完成。通过函数返回给调用者的api。但是如果使用匿名函数+闭包,怎么保证newVue({}),可以全局声明Vue变量,将上面的代码修改为如下代码:(function(global,factory){global.Vue=factory})(这,函数(选项){console.log(选项);});其中global对象在this中调用时传入,this代表window对象,而factory是实现整个逻辑的匿名函数,通过global.Vue=factory在window.Vue上定义匿名函数,这样newVue就可以了全局用于调用函数。参考模仿vue写自己的响应式框架(一)-Vue实现todo应用模仿vue写自己的响应式框架(二)-Vue对象创建