为了账号安全,请及时绑定邮箱和手机立即绑定

【前端骚操作】小程序《小小工具集合》初版

设想

小程序名《小小工具集合》,欢迎试用与建议

一直以来,我都在考虑是不是有一种集大成的查询工具,可以实现很多的查询功能,于是在很久以前,我就写了这个网站:

Only U

嗯,就是你输入内容,然后就可以自动匹配搜索引擎,如:“秋装 淘宝”,会根据最后空格后的淘宝,自动进入淘宝页面,如下:
淘宝

我猜没几个人用,所以就自娱自乐。

忽然间,我想到,弄个小程序,类似。但是小程序调用 webview 很麻烦,便打算做一个功能型小程序。

预览

预览图

上面这个是当前版本,本文只讨论第一版。

初版构思

初版功能就是检索我私藏的数据,至于数据嘛,这么多年的 Excel,网上找到后,转成 JSON 就妥了。

所以初版功能:邮编号、机场三字码、车牌简写与省市区匹配。

初版的 UI 是根据计算器来的,我在想,是不是一个显示屏就可以显示所有的内容……

初版实现

wxml

<text id='total'>{{totalCount}}条</text>
<scroll-view id='result-display' scroll-y>
  <text wx:for="{{results}}" wx:key="{{index}}">{{item + '
'}}</text>
</scroll-view>
<view id='input-container'>
  <input id='main-input' placeholder='输入搜索内容' focus="{{true}}" bindconfirm='search' bindinput='input' value="{{inputValue}}"></input>
  <button id='clear-button' bindtap='clear'>X</button>
</view>
<view id='buttons'>
  <button class='search-button' bindtap='search' wx:for="{{engines}}" wx:key="{{index}}" data-engine="{{item}}">{{item.name}}</button>
</view>

从上到下,检索条目、显示屏、输入框与功能按钮。

个人不喜欢太多层级的树,所以没有套个 container,算是 Web 的习惯吧。

wxss

/**index.wxss**/
#result-display {
  position: relative;
  height: 400rpx;
  padding: 40rpx;
  box-sizing: border-box;
  margin-top: 20rpx;
  border: 2rpx solid #999;
}

#total {
  position: absolute;
  top: 20rpx;
  right: 20rpx;
  display: block;
  color: #999;
  font-size: 24rpx;
}

#input-container {
  position: relative;
  margin-top: 20rpx;
}

#main-input {
  width: calc(100% - 140rpx);
  height: 80rpx;
  border: 2rpx solid #d8d8d8;
  padding-left: 40rpx;
  border-radius: 10rpx;
}

#clear-button {
  position: absolute;
  top: 10rpx;
  right: 18rpx;
  width: 64rpx;
  height: 64rpx;
  padding: 0;
  font-size: 26rpx;
}

#engines {
  height: calc(100% - 550rpx);
  margin-top: 20rpx;
}

.title {
  font-size: 32rpx; 
  color: #999;
  margin-left: 20rpx;
}

#buttons {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-evenly;
}

.search-button {
  position: relative;
  width: 30%;
  margin-bottom: 20rpx;
  font-size: 28rpx;
  font-weight: 900;
}

wxss 没啥可说的,看效果:

初版效果

js

//index.js
//获取应用实例
const app = getApp()
const AV = app.globalData.AV
let currentEngine = null // 当前锁定的引擎

Page({
  data: {
    engines: [],
    inputValue: '', // 搜索字符
    results: [], // 搜索出来的结果
    totalCount: 0, // 总数
  },
  //事件处理函数
  bindViewTap: function() {

  },
  clear() {
    this.setData({
      inputValue: '',
      results: [],
      totalCount: 0,
    })
  },
  input(e) {
    this.setData({
      inputValue: e.detail.value
    })
  },
  // 搜索
  search(e) {
    if (!this.data.inputValue) {
      wx.showToast({
        title: '请输入内容',
        icon: 'none'
      })
      return
    }
    this.setData({
      results: [], // 习惯性清空之前数据
    })
    const engine = e.target.dataset.engine
    // 按钮点击赋值新的引擎
    if (engine) currentEngine = engine
    this.getResult()
  },
  // 获取搜索结果
  getResult() {
    const value = this.data.inputValue
    const className = currentEngine.className
    this.localEngine(value, className)
  },
  // LeanCloud 自有的数据
  localEngine(value, className) {
    let querys = [] // 或条件
    for (const item of currentEngine.keys) {
      querys.push(new AV.Query(className)
        .contains(item, value))
    }
    wx.showLoading({
      title: '努力检索数据库中……',
    })
    AV.Query.or(...querys)
      .find()
      .then(res => {
        wx.hideLoading()
        if (!res.length) {
          wx.showToast({
            title: '没有找到相关结果',
            icon: 'none'
          })
          return
        }
        let results = []
        for (const item of res) {
          const resultObj = item.attributes
          resultObj.next = '-----------------'
          for (const key in resultObj) {
            results.push(`${key}: ${resultObj[key]};`)
          }
        }

        const totalCount = res.length
        this.setData({
          results,
          totalCount
        })

        if (totalCount > 99) wx.showModal({
          title: '内容超出100条',
          content: '建议检索条件更加丰富。',
          showCancel: false,
        })
      })
      .catch(err => {
        wx.hideLoading()
        console.log(err)
      })
  },
  // 获取所有可搜索引擎
  getEngines() {
    wx.showLoading({
      title: '加载引擎中……',
    })
    new AV.Query('Engines')
      .find()
      .then(res => {
        wx.hideLoading()
        this.setData({
          engines: Array.from(res, item => {
            return {
              name: item.get('name'),
              className: item.get('className'),
              keys: item.get('keys'),
              url: item.get('url')
            }
          })
        })
      })
      .catch(err => {
        console.log(err)
        wx.hideLoading()
      })
  },
  onLoad() {
    this.getEngines()
  },
  onShareAppMessage(res) {
    if (res.from === 'button') {
      console.log(res.target)
    }
    return {
      title: '实用的工具集合,你也来一个吧。',
    }
  }
})

分析代码

onLoad() {
  this.getEngines()
}

这句说明落地先获取引擎列表(这里说是引擎,只是命名,其实就是数据库表)。

获取到引擎对象后,转成我们需要的数据结构,在后续使用:

this.setData({
  engines: Array.from(res, item => {
    return {
      name: item.get('name'),
      className: item.get('className'),
      keys: item.get('keys'),
      url: item.get('url')
    }
  })
})

这些整理后的引擎,都会绑定在每个 button 的 data 数据上,好在后面点击的时候直接获取到。

每一个 button 都有这么个东西:data-engine="{{item}}"

然后此时页面就已经渲染好了,接下来就是交互了。

input(e) {
 this.setData({
   inputValue: e.detail.value
 })
},

这句是在输入内容的时候,把输入的值放到 data 的 inputValue 上,并且通过 wxml 我们知道,这个 inputValue 是绑定在 input 的 value 上的,这样就可以在后面使用的时候直接调用:this.data.inputValue 来直接获取 input 的 value,不用每次都 e.detail.value 了。

下面就是点击了。

search(e) {
 if (!this.data.inputValue) {
   wx.showToast({
     title: '请输入内容',
     icon: 'none'
   })
   return
 }
 this.setData({
   results: [], // 习惯性清空之前数据
 })
 const engine = e.target.dataset.engine
 // 按钮点击赋值新的引擎
 if (engine) currentEngine = engine
 this.getResult()
}

这里不说上面那个 X 按钮,那就是清空 input 的 value 以及上面显示屏内容功能。

search 是下面功能按钮的点击事件,做了这么几件事:

  1. 如果 input 没有 value,就直接提示并返回。
  2. 清空当前显示屏数据,避免用户郁闷数据串了。
  3. 将点击的引擎赋予到一个当前页面的全局变量中(当前页面的全局,不是 App 全局)。
  4. 一切正常,开始搜索结果。
getResult() {
  const value = this.data.inputValue
  const className = currentEngine.className
  this.localEngine(value, className)
}

这里主要是获取两个关键变量,value 自不用说,className 是我所用的云后端相关,无视即可。

localEngine 以及这个中间步 getResult 是为了后期拓展使用。

localEngine 内容看似很多,其实就是向服务器获取数据,然后排列展示在显示屏上,所以这里不占用篇幅多说,因为每个人的服务器或获取数据方式不同,无法概论。

到此,这个小程序就完成了,是不是还是蛮简单的。

终极效果

终极效果

这里尴尬的那个不是 bug 哦,那是输入框右下角确认(PC 是回车,我顺手点了回车)会默认使用当前引擎搜索内容,里面是输入了“粤D”回车,搜索的是之前的邮编号,当然没有东西了。


欢迎关注,如有需要 Web,App,小程序,请留言联系。

点击查看更多内容
2人点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
软件工程师
手记
粉丝
1.6万
获赞与收藏
893

关注作者,订阅最新文章

阅读免费教程

感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消