人生无趣且不易,一起找点乐子吧。欢迎评论,和文章无关也没问题。
上篇文章我们主要说到了列表的渲染,给定个数组,循环遍历“画”在界面上,最后我们也提到,如果想要改变界面,只要相应的改变对应数组的内容就可以了。
This time我们来谈下怎样从界面获得点击位置,然后在脚本里处理,并修改数组的相应位置的内容,也就是实现选座,离座的功能。
首先我们先来捋清一下思路,我们的选座需要什么功能,页面上许多的icon,当我们选中后点击,要触发选座事件,将我们点击的相应的icon所对应的数组元素改变。我们最初设想,有人选了的座位就显示成红色,没人选的就成绿色,表示可选,那我们就拿蓝色当做我们当前选择的位置好了。那这个功能的主要核心点就是,我从页面获得什么数据(被点击座位映射到数组中的位置),脚本里面怎样准确的处理到我们点击icon的对应数组信息?
思维敏捷的同学可能已经想到了,既然要改变所点击的icon对应的数组的信息,那只要获得那个icon所处数组的位置就可以了(也就是下标)。没错,我们只要从页面获取到点击icon的下标,相应的去改变数组的值就好。
那么问题来了,怎样得到icon的下标?这里呢,其实icon标签可以有个id属性(自定义属性),我们可以来设置,分别为icon赋予不同的id,在绑定的函数里,我们就来获取id当做下标来用。那么第一个icon的id就让他等于零,第二个等于1,依次下推。至于怎么实现,当然不用我们一个个手动输进去啦。我上次不是说的吗,那样手疼(即使是有文化的莽夫),但别忘了,我们的界面是通过循环画出来的,循环的时候靠的数组的item,因为我们只用到了他的内容,这次我们需要他的下标,它还有个默认的index属性啊,好好利用。
这次我们这样写:
<view wx:for="{{color}}" wx:for-index='x' wx:for-item="r">
<icon wx:for="{{r}}" wx:for-index='y' wx:for-item="c" type='success' bindtap='click' id='{{x*clo+y}}' color='{{c}}'></icon>
</view>
外层view循环有多少行,即二维数组里有多少一维数组,内部的icon再画出每一行的内容。这里没什么新内容,只是理解上上了层高度,我也一起帮大家捋下思路,我们都来给数组的index和item起了个别名,index理解为下标就可以,希望你的第一门编程语言是c或者java,如果是python可能会稍稍蒙一下(python的循环很少用下标引用,一般从迭代器中取)。我直接起别名是x,y了,这样恰好也是我们引用二维数组的习惯。item分别对应了r和c,没什么特别的深意,就是row和column,很好理解吧。其实核心在id怎样去写,多了个绑定事件click,我们等下讲,这里的处理,我认为是比较冗余了,但是我没找到更好的解决办法,也拿出来跟大家交流下吧。我这里返回的id其实是数组的第几个元素,也就是把二维数组换成一位数组后的下标,好像越解释越迷糊了。举个例子吧,比如三行三列的数组,第一行的最后一个元素下标是2,第二行第一个是3,就是这个意思。这里谈到下,其实id的内容不是限制的,可以是字符类型(也就是上面提到的自定义属性,属性是自己设置的),也就是说完全可以赋值“3 5 ”,当成3行5列来处理,但这时函数里面获得的也是char或者str类型,在后面的setdata步骤的时候会引起不必要的麻烦,往后看,后面详谈。大家可以去尝试,如果成功了,可能会比我这里少写几步吧。id属性里面的clo是js里面的数值(从后台获取的信息,理解成一行有多少个座位就好了),其实是自己定义的二维数组的列数,这样大家就明白了吧。(例如你在js里面定义了3x2的数组,记得定义clo变量为2,不用担心我们不能动态变化它,后面会谈。)
这里我们来分析下click函数的写法。首先我先讲下在函数里面变量的获取吧。
click: function (e) {
var th = this;
var id = e.target.id;
var y = (id)%this.data.clo;
var x = (id-y)/this.data.clo;
var col = 'color[' + x + '][' +y+ ']';
var color = th.data.color[x][y]
}
(this.data.clo和我们上面说的那个id属性里的clo是一个东西)
我们一个个来说,首先第一个th,没啥就是让他当this用,为什么要特意声明一次,这里要说一下,当你在一个函数中直接用this的时候不会出错,但是如果这个函数里面还有函数,在里面的函数里使用我们的this时,就会not define,在控制台就会出错。这时作用域的问题我没太去深入的理解,大家感兴趣去查查吧。第二个(this.data.clo 我们刚刚说了,他就是定义的二维数组列数,自己去定义它),id就是获取页面我们设置的那个id(也就是icon中自定义的那个id),通过函数的默认参数,我这里设成了e,通过e的target方法就可以去获的绑定标签的属性。后面的x,y当然就是我们要得到对应的二维下标了。但还是不明白,还是那个问题,为什么,不把页面的id设成id=“{{x y}}”,然后js得到后用splite去分割下分别给x,y。就不用像这样还要对id取余啊,做除法啊什么的。其实这里有原因。我们先跨过几步,先来说下setdate怎么实现。
this.setData({
color[x][y]: 'blue',
})
假设我们已经得到了x,y。但是我们可以通过上面的方法给color赋值吗?这里很可恶,会出错,他会说不认识color[x][y]。接下来是我的理解,在setData中,你的变量必须是“”不变的“,(很二的问题,不变还叫变量)比如你换成color【0】【1】就没问题,因为变量未定义,所以我们怎么处理这里呢。很简单,其实就是在setData外先把color【x】【x】(也就是先固定,再引用)对应的形式写好当成个字符串,然后用字符串替换图中的color【x】【y】。这就是为什么在上上张图中有
click: function (e) {
var th = this;
var id = e.target.id;
var y = (id)%this.data.clo;
var x = (id-y)/this.data.clo;
var col = 'color[' + x + '][' +y+ ']';
var color = th.data.color[x][y]
}
var col = 'color[' + x + '][' +y+ ']',这里赋值的内容就很好看懂了吧。回到最初的问题,页面为何不是id=‘{{x y}}’。我们来看col,这时的x和y是数值型,这样拼接完后col就是“color[0][1]”这种形式。如果按我们说的那种写col就是这种类型了“color[“0”][“1”]”,显然这种引用是错的,因为下标不能字符类型。那在得到x,y后强制转换不行吗?理论上是没问题的,但是强制转换那里还有坑,我用过几次网上查到的方法,皆以失败告终,转换挺麻烦的,我不知道现在的bug有没有修复,如果可以,其实大家完全可以采用上面说的那种方法。
最后一个变量color其实就是得到当前点击的那个位置,是什么颜色啦。然后我们根据他去处理。(看color数组对应位置的颜色)
这里我们分析一下,我们设置的是已选座位是红色,未选为绿,当前选择是蓝。
那么我们的函数就应该是
if(color=='red'){
提示此位置已被选
}else if(color == 'green'){
这里还要进行两次判断,是否已经选了座
if(已选)
提示 你已经选择了 不能重复选择
else
设置选择位置的color为blue
}else{
pass(先过吧,这里只剩蓝色没处理,我们后面处理)
}
怎样判断是否已经选座呢,这里其实和简单,我们定义一个变量,随意的定初始值为0吧,当我们成功选座后,就把他改为1,离座后再改为零,来当做我们是否选座的判定。(就是自定义一个开关,表示是否选座的状态,立一个flag)
红色的判定,内容大家可以随意写啦。无所谓啦(我这里提个警告,告诉用户已选)
if(color == 'red'){
wx.showModal({
title: 'Warning',
content: 'The seat have been choiced.',
success: function (res) {
console.log('用户点击确定')
}
})
}
我们来看下面的:(seatnow就是上面说的开关,看看你是否当前选了座)
else{
if (th.data.seatnow == 0) {//是否选择了座位 未选
this.setData({
id: id,//
x: x,//这里的东西我们要用来写离座的函数,直接留下,不用再进行获取了(对此函数无意,先记着我们把选择的座位id,x,y存下了,后面讲为什么)
y: y,//
})
wx.showModal({
title: 'Confirm',
content: 'Make sure you chose this seat ' + id + '(+1)',
success: function (res) {
if (res.confirm) {
th.setData({
[col]: 'blue',//选座成功,选择的位置编程蓝色,选座状态变为1
seatnow: 1
})
console.log('用户点击确定')
} else if (res.cancel) {
console.log('用户点击取消')
}
}
})
} else if (color == 'green') {//已选
wx.showModal({
title: 'Warning',
content: 'You have choiced a seat.',
success: function (res) {
console.log('用户点击确定')
}
})
} else {//已选 且为蓝色
wx.showModal({
title: 'UserInfo',
content: 'Username is ' + 'john',
success: function (res) {
if (res.confirm) {
console.log('用户点击确定')
} else if (res.cancel) {
console.log('用户点击取消')
}
}
})
}
}
这样我们整个的逻辑处理就算完成了。这里要说明,这个if其实已经是click函数里面的函数了,这里再用this就要出错了(回到了为什么有th = this的那条代码)。
还有个离座的处理。在页面写一个按钮,绑定事件leave,处理很好写,和上面没什么不同,就是把颜色换成green,而不是blue了。
leave:function(e){
var th = this;
var x = this.data.x;//
var y = this.data.y;//这里我们不再获取,click函数里面我们已经存了起来,直接拿来用(这里就用到了我们上面保存的座位信息,知道为什么了吧。我们需要下标在离座的时候把颜色变回来)
var id = this.data.id;//
var col = 'color[' + x + '][' + y + ']';
wx.showModal({
title: 'Confirm',
content: 'Are you want to leave this seat?',
success: function (res) {
if (res.confirm) {
th.setData({
[col]: 'green',
seatnow: 0
})
console.log('离开成功')
} else if (res.cancel) {
console.log('用户点击取消')
}
}
})
}
完成了,我给大家看下效果吧:
界面的设计大家自己去搞哈,我们就以第二行,第四个来做实验吧。点击:
确认:
这时候我们再点击其他绿色按钮:
点击红色的:
提示被选。我们离开座位试试:
点击离开:
确认:
、
ok,这次的文章就先到这里吧。希望对您有帮助,下次我们来谈谈怎样动态的生成数组,我们已经可以画出座位,还可以点击选座改变数组,从而改变座位布局。但是,最后一点,使用时,会有很多种班级的布局,不同的行列组合,每个教室都是一张图,我们当然还可以拿出莽夫的劲头,有多少个教室,我就画多少个界面。
如果不呢?这就是我们下次谈的内容。
当后台给我一个座位的字符串:"John None None Rose None",我就知道1号和4号座位上坐着人,别的地方都是空的。问题在于怎样根据这串字符去动态的生成color数组呢(生成了color数组,前面的绘制以及事件就都相应的完善了)。其实就是界面的初始化显示怎么去实现。(换种说法,我从数据库得到了个 六行八列 的消息,我怎样通过这个‘6 8’,生成那个color数组,从而动态改变了界面,真正使界面活起来。)
后记:
再次审看,啰里啰嗦,还是没讲太清楚,尤其是二维数组那块。其实很简单,for循环,有两个参数,item表示元素,index表示元素下标。再有就是取别名,无非就是为了在处理外层和内层循环时好理解罢了。
重点在于理解起的那几个别名分别代表什么。Fighting!