微信小程序 —— 懒人单词


目的

为了深入学习微信小程序编程,设计一款简洁的背单词的小程序。

开发前准备

1.页面结构

懒人单词小程序的页面有上下2个区域组成,content和tab。
content区域可以通过左右滑动实现标签页的切换。关于2个标签具体说明:

  • 单词学习:显示英语单词书。

  • 生词本:显示在单词书里添加的不认识的单词。

    ​ tab区域用于显示“单词学习”和“生词本”2个标签的标题。如果当前位于某个标签下,该标签页会显示红色,并且字体也为红色,其他标签页文字和线条显示白色。

2.目录结构

主要文件夹 说明
index 里面包含index.wxml,js,wxss和disbook.wxml
study 单词学习页面的结构、样式和逻辑
BookDetail 生词详情页面的结构、样式和逻辑

标签页切换

1.实现标签页的切换

​ swiper组件是滑块容器视图,用于轮播图,本项目用于标签页的切换。

​ 切换标签页有两种方式,一种是直接滑动content区域,另一种是点击tab区域中的某一个标签对应切换。先为3个tab-item绑定事件,并设置data-item属性。

<view class="tab-item {{tab==0?'active':''}}" bindtap="changeItem" data-item="0">单词学习</view>
<view class="tab-item {{tab==1?'active':''}}" bindtap="changeItem" data-item="1">生词本</view>

​ 上述代码中,data-item的值表示swiper 组件中对应的 swiper-item的索引。

​ 接下来修改content区域,为swiper组件的current属性绑定变量item,如下:

<view class="content">
  <swiper current="{{item}}" >

完成后在js文件中,将changeItem中 item的值设为data-item的值,如下:

changeItem: function(e) {
    this.setData({
      item: e.target.dataset.item,
    })
  }

使用e.target.dataset.item 会获取当前点击的元素的 data-item 的item 值。

​ 切换标签页后改变当前标签样式,通过判断变量tab 的值来为当前活跃的data-item 增加一个 active 样式,具体代码:

<view class="tab-item {{tab==0?'active':''}}" bindtap="changeItem" data-item="0">单词学习</view>
<view class="tab-item {{tab==1?'active':''}}" bindtap="changeItem" data-item="1">生词本</view>

active样式:

.tab-item.active {
  color: #c25b5b;
  border-bottom-color: #c25b5b;
}

为了更改tab值,给swiper组件绑定改变事件,如下:

<view class="content">
  <swiper current="{{item}}" bindchange="changeTab">

changeTab会在swiper组件发生标签页切换时调用。如下:

data:{
    item: 0,
    tab: 0,
  },
  changeTab: function(e) {
    this.setData({
      tab: e.detail.current
    })
  }

单词学习

1.单词书页面

view 布局 添加类名,绑定catchtab点击事件,如下:

<view class="list-item" catchtap="clickFirst">
      <image src="../images/four.jpg" />
      <view>四级单词</view>
</view>

bindtap :子元素使用bindtap绑定事件后,执行的时候,会冒泡到父元素(触发父元素上绑定的bingtap事件)

catchtap :不会冒泡到父元素上,阻止事件冒泡

catchtab点击事件的跳转用wx.navigateto,js代码如下:

clickFirst: function () {
  wx.navigateTo({
    url: '../study/detail?title=四级单词',
  })
},

wx.navigateto:保留当前页面,跳转到应用内的某个页面。但是不能跳到 tabbar 页面。使用 wx.navigateBack 可以返回到原页面。

wx.redirectTo:关闭当前页面,跳转到应用内的某个页面。但是不允许跳转到 tabbar 页面。

2.单词详情页面

分为内容区和按钮区,内容区需要从数据库中去获取单词信息,在应用到页面上。js代码如下:

var list = require("../../data/word-list");

Page({

 data:{

  words:"",

  soundmark:"",

  definition:"",

  show:false,

 },
 onLoad: function (options) {
    var title = options.title
    if (title) {
      wx.setNavigationBarTitle({
        title: title,
      })
    }
     var id = Math.floor(Math.random() * 499) + 1;
    var word = list.wordList[id];
    this.setData({
      words: word.content,//数据存储到data里的
      soundmark: word.pron,
      definition: word.definition,
      show: false,
      title: title,
    });
  },

list 是一个js 文件的单词数据,通过options获取上个页面的title来选择对应词书的单词,从list里面随机取单词,把获取到的数据存进data中,在页面显示,如下:

<view class="cet">
  <view class="wordPart">
    <text class="word">{{words}}</text>
    <view class="soundmark">
           <image class = 'soundmark-icon' src = "../../pages/images/pron-icon.png"></image>
           <text class = "word-pron" bindtap='read'>|{{soundmark}}|</text>
        </view>
  </view>
  <text wx:if = "{{show}}" class = "word-definition">{{definition}}</text>
</view>

内容区显示完成后,来编写按钮区,添加button,在按钮上绑定监听事件,如下:

 <view class="btns">
    <button class = "button miss" catchtap='show' wx:if='{{!show}}'>不认识</button>
    <button class = "button miss" wx:if='{{show}}'>已加入错词本</button>
    <button class = "button next" catchtap='next'>下一个</button>
    <button class = "button back" catchtap='back'>返回首页</button>
  </view>

wx:if =‘{{!show}}’ 来判断是否渲染该代码块,给show默认赋值 false,点击后 为true ,在将该单词加入云数据库wordlist里,代码如下:

show: function () {
    this.setData({
      show: true
    })
    db.collection('wordlist').add({
      data:{
        content:this.data.words,//调用上面data里的数据
        definition:this.data.definition,
        pron:this.data.soundmark,
      }
    }).then(res=>{})

  },

点击下一个按钮,在从list 中随机取出一个单词,代码如下:

 next: function () {
    var data = {
      title: this.data.title
    }
    this.onLoad(data);
  },

3.生词本

在标签页切换到生词本时,生词本将从云数据库中调出所有单词,显示在页面上,代码如下:

<scroll-view class="content-disbook" scroll-y><!-- scroll-view 滚动视图,scroll-y 纵向滚动 ,并在WXSS里添加一个滚动高度  -->
  <view wx:for="{{DataList}}" wx:key="_id"><!-- wx:for 遍历显示数据 -->
      <view class="errorword">  
        <view data-val="{{item._id}}" bindtap="transfer">{{item.content}}</view>
      </view>
  </view>
</scroll-view>

scroll-view 组件用于实现可滚动视图区域,scroll-y 允许纵向滚动,scroll-x 允许横向滚动。

生词本列表显示写在onShow()事件中,onShow方法是在每次从小程序的前后台切换时都执行的,onLaunch方法是在小程序加载时执行的,因为该页面会多次切换所有选择onShow(),代码如下:

var opid = wx.getStorageSync('openid')
onShow:function(){/* 刷新的数据写在onshow()里 */
    
    let THIS = this
    db.collection('wordlist').where({
      _openid:opid
    }).get().then(res => {
      THIS.setData({
        DataList:res.data
      })
    })
 
  },

生词本显示的单词应该是登陆该小程序用户自己添加的,所以应该获取用户的openid,来和数据库中单词的_openid 字段进行配对,通过调用云函数来获取打开小程序用户的openid,代码如下:

// 云函数入口文件
const cloud = require('wx-server-sdk')

cloud.init()

// 云函数入口函数
exports.main = async (event, context) => {
  const wxContext = cloud.getWXContext()

  return {
    event,
    openid: wxContext.OPENID,
    appid: wxContext.APPID,
    unionid: wxContext.UNIONID,
  }
}

在transfer 点击事件中使用方法e.target.dataset.val会获取当前点击的元素的val 里的当前单词_id值,通过对应id值跳转到对应单词的详情页面,代码如下:

transfer(e){
    var id=e.target.dataset.val;
    wx.navigateTo({
      url: '../BookDetail/BookDetail?id='+id,
    })

  },

跳转到生词本单词的详情页面,页面结构:内容区和按钮区,代码如下:

<view wx:for="{{words}}" wx:key="*this">
  <view class="cet" >
    <view class="wordPart">
      <text class="word">{{item.content}}</text>
      <view class="soundmark">
            <image class = 'soundmark-icon' src = "../../pages/images/pron-icon.png"></image>
            <text class = "word-pron" >|{{item.pron}}|</text>
          </view>
    </view>
    <text  class = "word-definition">{{item.definition}}</text>
    <view class="btns">
      <button data-val="{{item._id}}" bindtap="remove">已认识</button>
      <button class = "button back" catchtap='back'>返回生词本</button>
    </view>
  </view>
</view>

words 也可以遍历循环,直接{{words.属性名}} 调用

在生词页面跳转到单词详情页面时,初始加载写在onLoad()里,代码如下:

Page({
  data:{
    words:"",
  },
  onLoad:function(options){
    var ids=options.id;//将列表页面的id赋值
    let that=this
    db.collection('wordlist').where({//通过id查询数据
      _id:ids,
    }).get().then(res => {
      // res.data 包含该记录的数据
      that.setData({
        words:res.data
      })
    })

已认识按钮点击后执行删除操作,从数据库中删除该单词,代码如下:

remove:function(e){
      var id=e.target.dataset.val;
      db.collection('wordlist').where({
        _id:id //通过id 删除
      }).remove({
        success: function(res) {
        }
      })
      wx.navigateBack()
    },

暂时小程序的基本功能都已实现了,未来还会继续添加完善更多的功能,比如增加单词的趣味性玩法,好友PK等等。

下面附上小程序截图:


CSS样式代码我就不写了,本人审美不行。


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM