|
作者:苏雄伟,来自原文地址 一:点击编译为什么老是弹出设置框在对微信小程序的代码进行了一些调整以后,希望编译运行起来看看,结果却老是弹出自定义预览,要咱们填写启动页面和页面自定义参数等,如下图
即使我们填写了,点击编译,也会弹出,为什么? 一开始我也不明白,老是点那个,后来我才发现,这个工具把咱们误导了,这里面有两个相关并不一样的功能,一个是编译运行,一个是编译设置,下面我们来说说它俩。 编译运行是上面的那个图标,它的快捷键是ctrl+b,它的作用是编译修改过的代码并运行调试,也就是我们想要的编译运行功能,如下图所示:
编译设置是下面那个图标+编译文字(有点误导),它实际的作用就是编译设置,就是当程序启动时首先启动那个界面,并且设置传给那个界面的参数,如下图:
那么编译设置应该怎么设置呢?我给下实例图:
ctrl+b启动时打出的日志,如下: page/component/index: onLoad have been invoked index.js [sm]:17 Object {name: "bright789", year:"2017"}
这个就是方便我们更好的调试,毕竟有的页面不在第一界面,但经过编译设置以后,在调试阶段就可以变成第一,调试完后又可以修改回来! 二:示例使用到了大量的for+i+function+function组合代码到底怎么理解在微信小程序示例代码里面使用到了非常多的for+i+function+function这种组合代码,有时看了头晕,到底是什么意思?起什么作用或者说解决什么问题?它跟JavaScript的closure(闭包)有什么关联?今天我们就来学习一下它。 下面使用一个作为例子: var toastNum = 3var pageData ={}pageData.data ={}for(var i =0; i <= toastNum; ++i) { pageData.data['toast'+i+'Hidden'] = true; (function (index) { pageData['toast'+index+'Change'] = function(e) { var obj = {} obj['toast'+index+'Hidden'] = true; this.setData(obj) } pageData['toast'+index+'Tap'] = function(e) { var obj = {} obj['toast'+index+'Hidden'] = false this.setData(obj) } })(i)}
Page(pageData) 这段代码来自微信小程序示例代码: page/component/component-pages/wx-toast/wx-toast.js 这段代码的代码的主要意思是通过一个for循环,把object对象pageData里的object变量data的toast0Hidden,toast1Hidden,toast2Hidden,toast3Hidden变量赋值都赋值成true,把object对象pageData里toast0Change,toast1Change,toast2Change,toast3Change变量分别赋值一个匿名回调函数,此回调函数如下: function(e) { var obj = {} obj['toast'+index+'Hidden'] = true; this.setData(obj) }
把object对象pageData里toast0 Tap,toast1 Tap,toast2C Tap,toast3Tap变量分别赋值一个匿名回调函数,此回调函数如下: function(e) { var obj = {} obj['toast'+index+'Hidden'] = false this.setData(obj)}
但是为什么for循环里面还有一个 (function (index) {……})(i)
这样的东西呢?是不是多此一举,让代码复杂化,能不能去掉,如果不是不能,哪又起什么作用呢? 为了理解这个东西,我们先学习一点点javascript的作用域的知识 在javascript的世界里,只有全局作用域和函数作用域,没有块作用域,那么什么是全局作用域,什么又是函数作用域呢?全局作用域就是在全局范围都起作用的一些,其中囊括在函数之外定义的变量和函数内没有声明为var的变量,如果上面的toastNum,pageData,特别指出的是i它也是,而函数作用域就是在函数以内的作用范围,包括参(),函数体{}内,比如上面代码的var obj={}中的obj和函数参数index。 为了看到效果,我们把去掉,调整代码如下: for(var i = 0; i<= toastNum; ++i) { pageData.data['toast'+i+'Hidden'] = true; pageData['toast'+i+'Change']= function(e) { var obj = {} obj['toast'+i+'Hidden'] = true; this.setData(obj) } pageData['toast'+i+'Tap'] = function(e) { var obj = {} obj['toast'+i+'Hidden'] = false this.setData(obj) }}
调试时看变量初始化,好像都正常,该有的都有了
那咱们继续,点击界面上其中的某个按钮,调试结果:
调试的i,怎么变成4,进而形成toast4Hidden,从上上图我们知道,我们最高是3,怎么跑出4来了?哦,原来,i由于javascript里没有区块作用域,所以i现在全局作用域,并且只有一个i,当for循环完后i就变成了4,所以当回调函数使用它时就是4了,那么跟我们想的不一样,我们想的是当点击第一个btn时,就是相应的toast1Hidden,那怎么办?一种通用的就办法就引了函数作用域,就是javascript所说的closure(闭包),就是把i当参数传入一个函数,然后被传入的函数有一个参数是用来复制保存当时的i的,如下代码: (function (index) {……})(i)
所以现在只有4个index变量(for循环以后),复制缓存i的四个状态:0,1,2,3,而这4个index的作用是函数作用域,在上面function(){}的{}里头有效,所以就可以实现我们之前想的目标,即函数里的index是对应的。 最后代码我贴一下,大家自己去体会下之间的不同: Js文件代码: var toastNum = 3var pageData ={}pageData.data ={}for(var i = 0; i<= toastNum; ++i) { pageData.data['toast'+i+'Hidden'] = true; (function (index) { pageData['toast'+index+'Change'] =function(e) { var obj = {} obj['toast'+index+'Hidden'] = true; this.setData(obj) } pageData['toast'+index+'Tap'] = function(e){ var obj = {} obj['toast'+index+'Hidden'] = false this.setData(obj) } })(i)}Page(pageData)
Wxml文件代码: <viewclass="page"> <view class="page__hd"> <textclass="page__title">toast</text> <textclass="page__desc">toast提示</text> </view> <view class="page__bd"> <view class="btn-area"> <view class="body-view"> <toasthidden="{{toast1Hidden}}" bindchange="toast1Change"> 默认 </toast> <button type="default"bindtap="toast1Tap">点击弹出默认toast</button> </view> <view class="body-view"> <toasthidden="{{toast2Hidden}}" icon="warn"bindchange="toast2Change"> 设置icon </toast> <button type="default" bindtap="toast2Tap">点击弹出设置icon的toast</button> </view> <view class="body-view"> <toasthidden="{{toast3Hidden}}" duration="3000"bindchange="toast3Change"> 设置duration </toast> <button type="default"bindtap="toast3Tap">点击弹出设置duration的toast</button> </view> </view> </view></view>
|