日复一日,反反复复,终于完成了小程序的项目.。这篇文章我就对自己的项目中用到的array方法结合具体的功能进行综合的分析
正当项目即将完成之际,恰逢项目经路来了一句,搜索框我觉得高亮显示会更好一些,把这个需求弄一下.恰同学少面年,跟项目经理争执了半天也没有个结果.最后我不要你觉得,我要我觉得,惨败收场.此时心里面不知道多少个???what?.没办法,硬着头皮也得来呀.简单分析后,其实原理并不难
原理:字符串替换
基本想法就是字符串替换。现在的问题简化成了:如何把一段字符串中的指定的内容替换成另一个内容:
var str = "abcdefgbefab"
// 目标: 把str中的b全部换成b
// 普通字符串替换:str.replace(目标字符串,要替换的字符串),它的返回值是替换之后的字符串,注意它不会修改原字符串。
// 它的问题是,它只能替换一次。如上,我们有两个b需要替换,那又该怎么办呢?
// - 循环
// - 正则
此时到这里以后,我觉得可以使用正则来进行解决
<script>
// 实现正则替换
var str ="abdAd";
var keywork = "ab"
// 目标是:
// 把所有的a替换成a
// 请开始你的表演
// replace如果不用正则,只能换一次
// var str1 = str.replace("a",'a')
// replace(正则,函数)
// /a/gi :正则
// g表明要做全局匹配。只匹配出所有的子串。
// i表明匹配不分大小写。
// new RegExp('a','gi'); 用构造器的方式来创建正则表达式就可以把
// 第一个参数写成变量
// 如果在字符串用正则匹配到了内容,则会去执行函数。
// 函数的执行细节是:
// - 参数obj是匹配到的内容
// - 返回值是替换之后的结果
var str1 = str.replace(new RegExp(keywork,'gi'),function(obj){
console.log(obj)
return ''+obj+''
})
console.log(str1); // 'abAdd'
</script>
在计算属性中定义
this.searchSuggestions
是搜索是获取的数据是一个数组
<script>
....
computed: {
// 补充一个计算属性对searchSuggestions中的数据做高亮
cSearchSuggestions () {
// 创建正则表达式
const reg = new RegExp(this.keyword, 'gi')
return this.searchSuggestions.map(str => {
// 原来是:str
// 替换成:对关键字进行高亮之后的字符串
const str1 = str.replace(reg, function (obj) {
return `${obj}`
})
return str1
})
}
},
}
</script>
使用array.map返回的就是一个数组.所以此时只需要对当前的数组进行遍历就可以了
但是问题又出现了
我们替换的的是html,那么如何渲染 到小程序上哪?
使用小程序的 rich-text
组件 nodes后面跟的是需要渲染的数据
<rich-text nodes="HTML字符串">rich-text>
搜索区域的历史记录涉及的东西也比较多.之前在做vue的项目中也比较常用.
对于历史记录的用一个数组来进行保存,并且要做数据的持久化.所以里面也会用到Storage相关的api.因为使用的是uniapp进行开发的,所以相关的api进行查阅文档就可以了.开始进入正题吧.
当项目经理找到我的时候,给我提了一个我需求.要求:点击的历史记录在被点击以后,选项要被提前.点击相关的选项要进入到相关的搜索结果区域
以上就是需要.下面开始功能的完善
首先是关于数据重复的问题:当我们添加数组的时候,可以先进行判断.
html结构
<input type="text" @focus="changeColor" :placeholder="value"
@input="getKey" v-model="word"
@confirm="confirmSeach"
>
js
// 保存历史记录(获取本地数据)
hisArr:uni.getStorageSync('history')||[]
点击回车以后,把我们的数据添加到数组中
// 输入框点击回车确定
confirmSeach(){
// 保存搜索的数据
const str=this.word
// 判断数组中是否有相同的值
const data=this.hisArr.indexOf(str)
// 若索引不等于-1,则说明存在值
if(data!==-1){
// 删除数组中的值
this.hisArr.splice(data,1)
}
// 将当前点击的数组提前
this.hisArr.unshift(str)
// 将数组保存到本地
uni.setStorageSync('history',this.hisArr)
// 清空数据
this.word=''
// 清处联想建议
this.resultArr=[]
},
此处我们使用了indexOf来进行判断,当然也可以使用其他的方法.
在商品列表点击的时候那,会进行token的验证,如果此时用户没有登录,我们会让用户进行登陆以后在进行购物车的添加.随后,又有一种新的突破方式,就是.用户没有登录,我们将添加的购物车数据保存到本地.等到用户登录的时候,我们在添加到购物车中.而我在项目中用到的就是这种方式
效果如下:
重复的数据我们使数量进行加加就可以了,不是重复的数据我们在添加到数组中
定义的数据
//uni.getStorageSync('item')获取本地的保存的商品记录
carList:uni.getStorageSync('item')||[]
// 点击加入购物车
addItem(){
// 将数据保存到购物车中
// 保存到本地中
// 定义一个对象保存数据
const obj={
// 商品的id
goods_id:this.imgMsg.goods_id,
// 商品的名字
goods_name:this.imgMsg.goods_name,
// 商品的价格
goods_price:this.imgMsg.goods_price,
// 商品的数量
goods_number:1,
// 商品的图片
goods_small_logo:this.imgMsg.goods_small_logo
}
// 判断商品是否重复
var status= false
// 遍历数组
this.carList.forEach((item,index)=>{
// 如此时传入的对象id与数组中的对象id相同则说明存在某值
if(item.goods_id===obj.goods_id){
// 商品数量++
item.goods_number++
// 修改状态
status=true
return
}
})
// 如果status不等于true
if(status===false){
// 此时说明数据不重复
this.carList.push(obj)
}
// 消息提示添加购物车成功
uni.showToast({title:"添加购物车成功"})
// 将数据保存到本地
uni.setStorageSync("item",this.carList);
},
此处我们定义可一个变量status来判断遍历的情况,当然也可以使用其他方法
const data = this.carList.find(item => {
return item.goods_id === obj.goods_id
})
// ,有值则为true
if(data){
data.goods_number++
}
// 如果没有值则返回的是undefined
else{
this.carList.push(obj)
}
//获取数据后将获取的数据
// 保存到数组中
this.textArr.push(...message.goods)
//message.good是一个数组
//第二种方法使用concat
this.textArr=this.textArr.concat(message.goods)
一般情况下,当用户选中了某个商品加入购物车的时候,我们就认为用户会有买的想法,所以此时我们可以自定义一个加入购物车的状态。当我们添加商品进入购物车的时候,我们就认为这个状态是一个true。
商品页的js
// 定义一个对象保存数据
const obj={
// 商品的id
goods_id:this.imgMsg.goods_id,
// 商品的名字
goods_name:this.imgMsg.goods_name,
// 商品的价格
goods_price:this.imgMsg.goods_price,
// 商品的数量
goods_number:1,
// 商品的图片
goods_small_logo:this.imgMsg.goods_small_logo,
//添加商品,默认选中
goods_status:true
}
此时我们进入js的时候我们加入的商品状态就应该是这个样子
默认的选中状态,在点击了以后发生状态的改变。
接下来我们可以使用计算属性来确定全选的状态,可以根据各个状态的个数来进行判断
此时我们可以使用arr.filter()
购物车的js
// 能否找到false
//遍历商品的数组,判断data,如果data有值就说明有一个状态是没有选中的
if(this.itemList){
const data= this.itemList.find(i=>{
return i.goods_status===false
})
// 找到就是有值
if(data){
// 保存数据
//此时返回false状态就行
return false
}
// 没有值就是undefined
//没有值就说明都是true,都是选中的状态
return true
}
此时我们就实现了点击单选后实现全选的状态
接下来就是实现点击全选和全不选的问题
思路实现,获取当前全选的状态,点击后设置为!status取反的状态,
根据当前的状态对数组进行判断,使数组中的数据全部设置为当前全选的状态
// 点击全选的切换
changeAllCheck(){
// 获取当前点击的状态
const status=!this.allCheck
// 点击全选的切换
this.itemList.forEach(i=>{
// 若当前点击的是true则所有的单选都需要是true
if(status){
i.goods_status=true
// 若所有的都是false则都需要时false
}
else{
i.goods_status=false
}
// 保存本地数据
uni.setStorageSync('item',this.itemList)
})
},
对于总价,遍历数组的时候进行判断,若此时的状态是false,那么就跳过,如果是true那么就是总数相加
// 计算总价
addNum(){
var result=0
// 遍历数组
if(this.itemList){
this.itemList.forEach(i=>{
// 如遍历到当前状态是false,直接return
if(i.goods_status===false){
return
}
// 状态为true直接进行计算,获取总价
result=result+(i.goods_price*i.goods_number )
})
}
return result
}
使用计算属性获取到计算的数量,ruo当前选中的状态是true则我们可以还是用filter返回一个数组,根据数组的长度来进行判断
// 获取选中的个数
checkNum(){
// 获取选中的个数
if(this.itemList){
return this.itemList.filter(i=>{
return i.goods_status===true
})
}
},
// 点击数量进行增减
indecrease(id,index){
// 若此时点击了减一
if(id===-1){
this.itemList[index].goods_number+=id
if(this.itemList[index].goods_number<=1){
this.itemList[index].goods_number=1
}
}
if(id===1){
this.itemList[index].goods_number+=id
if(this.itemList[index].goods_number>=10){
this.itemList[index].goods_number=10
}
}
// 保存数据
uni.setStorageSync('item',this.itemList)
},
此处传入两个参数,一个是1或者是-1,另一个是索引
数组的方法在是非常常用的,在平常的项目中可以自己总结哪些地方用到了这些方法,以及解决方法的思路.
推荐参考:
https://developer.mozilla.org/zh-CN/docs/Glossary/array
项目地址:
https://gitee.com/monhly/applets