第一个微信小程序:默写界面的规划和布置

准备工作

一开始参考了咩咩单词的 UI,然后一直陷在修改 css(wxss)当中,而我作为一个初学者也是搞了老半天终于做出一个像样的界面,后来还是觉得太丑。后来陈教授告诉我,有个叫做“小程序示例”的小程序可以参考一下。小程序示例就是一个官方的组件和 UI 的示例库,其实就是 weui,但是这个小程序木有源代码。后来在 github 上面搜了一下 weui,找到一个 weui 团队出的小程序源码,也算是官方的吧,地址如下:

weui github 地址

weui 官方网址

weui for 小程序

打包下载下来之后,阅读说明并在微信开发者工具中导入项目并查看里面的 wxml 是怎么写的。如果要在自己的项目中运用到 weui,那只需将文件夹内的 weui.wxss 文件放在自己项目的根目录或者是随便啥目录(我放在我新建的 style 文件夹下面),然后在 app.wxss 中全局引入 weui 的 css:

1
@import "style/weui.wxss";

想要用到小程序里面的标题和副标题样式,那还需要在 app.wxss 中写上相关的样式。注意在 app.wxss 中设置的样式全局有效,如果在特定的页面需要修改,那就再特定页面的 wxss 文件中进行添加即可。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
page {
  background-color: #f8f8f8;
  font-size: 16px;
  font-family: -apple-system-font, Helvetica Neue, Helvetica, sans-serif;
}
.page__hd {
  padding: 25px;
}
.page__bd {
  padding-bottom: 40px;
}
.page__bd_spacing {
  padding-left: 15px;
  padding-right: 15px;
}

.page__ft {
  padding-bottom: 10px;
  text-align: center;
}

.page__title {
  text-align: center;
  font-size: 30px;
  font-weight: 400;
}

.page__desc {
  margin-top: 5px;
  color: #888888;
  text-align: center;
  font-size: 15px;
}

.page__exp {
  margin-top: 5px;
  color: #888888;
  font-style: oblique;
  text-align: center;
  font-size: 15px;
}

默写练习的页面

默写页面如上,也是最重要的功能之一。从上至下分别为标题、副标题、副标题 2、6 个输入带表头以及警示的表单和 3 个按钮。他们能够显示单词、所需要默写的时态、单词例句、6 个输入框,还有检查、提示、跳过 3 个按钮。

在当前页面的 js 文件中,在一开始应当引入自己想要的数据内容,我将所有的数据文件储存在 conj_v1.js 中。比如:

1
2
3
//获取应用实例
const app = getApp();
const list = require("../../data/conj_v1.js");

首先是显示单词、所需要默写的时态、单词例句,这三个变量分别用双大括号括起,并在 js 文件中根据单词随机更改他们的显示值。代码如下:

1
2
3
4
5
<view class="page__hd">
  <view class="page__title">{{content}}</view>
  <view class="page__desc">{{shitai_chinois}}</view>
  <view class="page__exp">{{par_exemple}}</view>
</view>

下方的 list.conjAnswer 是动词变位的所有数据,而 idx 是取随机数,随机数的范围是以 6 个间隔为单位的数字间进行选取,也就是说分别在 0,6,12,18 等等数字中随机挑选(因为有 6 个人称,详见另外一篇文章)。

1
2
3
4
5
6
7
onLoad: function() {
    var idx = (Math.floor(Math.random() * app.globalData.wordListMax)) * 6 //从单词总数中抽取号码,数字的形态为0,6,12,18等,该数字对应的行为Je
    var word_je = list.conjAnswer[idx] //获取一个单词Je列的所有内容
    var word_tu = list.conjAnswer[idx + 1]  //获取一个单词Tu列的所有内容
    var word_il = list.conjAnswer[idx + 2]  //获取一个单词Il列的所有内容
    var par_exemple = word_je.scraper //获取例句
    var explication = word_tu.scraper //获取解释

当 idx 值取 0 时,word_je 就是某一个单词在第一人称单数的情形下所有的时态并含一句例句组成的对象。于是 idx+1 便是第二人称单数的所有内容,以此类推。 形如:

1
{ "word": "être", "scraper": "Je ne suis pas un verbe comme les autres !", "fuhe_guoqushi": "j'ai été", "zhichenshi_xianzaishi": "je suis", "weiwancheng_guoqushi": "j'étais", "Plus-que-parfait": "j'avais été", "jiandan_guoqushi": "je fus", "xian_guoqushi": "j'eus été", "jianglaishi": "je serai", "xian_futur": "j'aurai été", "zuijin_futur": "je vais être", "tiaojianshi_xianzaishi": "je serais", "jiaojianshi_guoqushi": "j'aurais été", "xunishi_xianzaishi": "que je sois", "xunishi_weiwanchengguoqushi": "que je fusse", "xunishi_yuguoqushi": "que j'eusse été", "xunishi_guoqushi": "que j'aie été", "minglingshi": "sois", "fenci": "étant" }

由于在设置页面中我们可以设定背词范围以及时态范围,那么普通、进阶、非常用,每种情况对应这一个数组。当背诵进阶时态时,则是普通、进阶时态之和;当背诵非常用时态时则是普通、进阶、非常用时态之和。当按钮关闭之时,数组即为空,加上了也没用。 (详见另外一篇文章)

1
2
3
4
5
6
7
8
shitai_choose = shitai_choose
  .concat(app.globalData.advanced_shitai)
  .concat(app.globalData.extra_shitai); //拼接三个时态的数组
var idx_shitai_num = Math.floor(
  Math.random() * (shitai_choose.length - 2 + 1) + 2
); //统计新的数组长度,并以此为范围取随机数
var idx_shitai = shitai_choose[idx_shitai_num - 1]; //选择新的数组中idx_shitai_num-1个元素,该元素为下面switch的case值(时态)
console.log(idx_shitai_num); //查看用

随机选完时态之后,则会进入对应的 case,这里用 switch 实现(以直陈式 复合过去时为例):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
switch (idx_shitai) {
      case 2:
        var random_shitai_chinois = "直陈式 复合过去时";
        var word_je = list.conjAnswer[idx]; //获取Je行,同下
        var word_tu = list.conjAnswer[idx + 1];
        var word_il = list.conjAnswer[idx + 2];
        var word_nous = list.conjAnswer[idx + 3];
        var word_vous = list.conjAnswer[idx + 4];
        var word_ils = list.conjAnswer[idx + 5];
        var shitai_je = word_je["fuhe_guoqushi"];  //获取Je行中的复合过去时,同下
        var shitai_tu = word_tu["fuhe_guoqushi"];
        var shitai_il = word_il["fuhe_guoqushi"];
        var shitai_nous = word_nous["fuhe_guoqushi"]
        var shitai_vous = word_vous["fuhe_guoqushi"];
        var shitai_ils = word_ils["fuhe_guoqushi"];
        break;

然后将这些得到的数据赋予给 data,以便让后面的检查按钮和提示按钮用到:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
this.setData({
  content: word_je.word,
  shitai_chinois: random_shitai_chinois,
  par_exemple: par_exemple,
  shitai_je: shitai_je,
  shitai_tu: shitai_tu,
  shitai_il: shitai_il,
  shitai_nous: shitai_nous,
  shitai_vous: shitai_vous,
  shitai_ils: shitai_ils,
});

默写输入框

在默写输入框的最前面有一个提示人称的标签,以 Je 为例。此外这里在 placeholder 中加了默认显示的语句,这里我把它变成简单的帮助。value 之所以是一个变量,是因为当我们背完一个词或者是跳过到下一个词之时,输入框内之前输入的内容需要清空。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
<view class="weui-cell weui-cell_input">
  <view class="weui-cell__hd">
    <view class="weui-label">JE</view>
  </view>
  <view class="weui-cell__bd">
    <input
      class="weui-input"
      placeholder="écrivez-le complètement ici"
      bindinput="input_je"
      value="{{value_input}}"
    />
  </view>
  <view class="weui-cell__ft">
    <icon type="{{iconType_je}}" size="23" color="{{iconColor_je}}"></icon>
  </view>
</view>

输入框需要在 js 文件中绑定事件,以上述的输入框为例,bindinput 为 input_je,那么在 js 文件中:

1
2
3
4
5
6
input_je: function(e) {
    console.log(e);
    this.setData({
      input_je: e.detail.value
    })
  },

在输入框的最后,相当于是提示用户的默写究竟对不对,这里用 icon 来表示。当用户答对时,icon 的颜色为绿色、显示对勾;当用户答错时,icon 的颜色为红色、显示感叹号。icon 和颜色均为变量,在 js 文件中如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
if (this.data.input_je == this.data.shitai_je) {
  //当用户答对时
  var iconType_je;
  var vrai_je = 1; //用户答对了
  this.setData({
    iconType_je: "success", //显示对勾
    iconColor_je: "#44b549", //微信绿
  });
} else {
  this.setData({
    iconType_je: "warn", //显示感叹号
    iconColor_je: "#E64340", //微信红
  });
}

检查、提示和跳过按钮

检查按钮用来显示用户是否答对,提示按钮用来提醒用户,跳过按钮则可以让用户跳过该单词和变位。类型分别为:primary,default,warn。

1
2
3
4
5
6
7
8
9
<view class="weui-btn-area">
  <button class="weui-btn" type="primary" bindtap="check">检查</button>
</view>
<view class="weui-btn-area">
  <button class="weui-btn" type="default" bindtap="hint">提示</button>
</view>
<view class="weui-btn-area">
  <button class="weui-btn" type="warn" bindtap="next_conj">跳过</button>
</view>

每个按钮需要在 js 中绑定对应的事件,这里以提示按钮为例:提示按钮绑定的事件为 hint,则在 js 中有一段对应的函数,其主要以对话框的方式(wx.showModal)显示上面默写的答案。数据均为 data 中的数据(也就是之前 setData 之后的数据)。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
 hint: function() {
    wx.showModal({     //显示弹出对话框
      title: '提示',       //对话框最上方显示“提示”
      content: this.data.shitai_je + '\r\n' + this.data.shitai_tu + '\r\n' + this.data.shitai_il + '\r\n' + this.data.shitai_nous + '\r\n' + this.data.shitai_vous + '\r\n' + this.data.shitai_ils,   //显示内容
      success(res) {
        if (res.confirm) {
          console.log('用户点击确定')
        }
      }
    })
  },

在跳过以及检查答对的情况下,我们需要清空输入表单的所有内容以及最后的红绿图标反馈,那么就需要将 value_input 以及 iconType 都清空:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
next_conj: function() {
    //判断是否有打开过页面
    if (getCurrentPages().length != 0) {
      //刷新当前页面的数据
      getCurrentPages()[getCurrentPages().length - 1].onLoad()
    }
    this.setData({
      iconType_je: null,
      iconType_tu: null,
      iconType_il: null,
      iconType_nous: null,
      iconType_vous: null,
      iconType_ils: null,
      value_input: null,
    })
  }
updatedupdated2020-05-272020-05-27

以上是自己提供的广告