用Taro做個微信小程式Todo, 小白工作記錄

微信小程式框架: Taro

做微信小程式的框架, 幾個比較主流的:

前兩者都是Vue風格的, Taro是React的.

本篇本著學習的目的, 用Taro做一個簡單的小程式.
程式碼在這裡: //github.com/mengdd/mini-program-todo
這是預覽圖:
todo list

背景:
一直做Android開發, 最近想把其他各種技術都擼一擼, 拓展一下視野.
之前練過微信小程式原生開發的例子, 基本上只知道個大概, 翻書馬冬梅, 合書馬什麼梅?
所以這次用框架了, 覺得還是要有個輸出, 這樣印象深刻一些.

所以本文是從一個小白的角度, 手把手做練習的.

Taro程式環境

這部分參考:

要有node環境, 推薦用nvm來管理.

需要安裝CLI工具:

npm install -g @tarojs/cli

創建項目並運行

創建項目

創建模板項目:

taro init myApp

在這個階段會有一些問題要回答.

* 請輸入項目介紹! My awesome project blablabla.
* 是否需要使用 TypeScript ? Yes
* 請選擇 CSS 預處理器(Sass/Less/Stylus) Sass
* 請選擇模板 默認模板

完了之後會自動安裝依賴:

npm install

然後就成功啦!

運行

Taro需要運行不同的命令, 將Taro程式碼編譯成不同端的程式碼, 然後在對應的開發工具中查看效果.

這裡僅說微信小程式. 還是需要微信開發者工具:
//developers.weixin.qq.com/miniprogram/dev/devtools/download.html

import這個項目就行了.

開發前微信開發者工具的項目設置要注意:

需要設置關閉ES6轉ES5功能, 開啟可能報錯.
需要設置關閉上傳程式碼時樣式自動補全, 開啟可能報錯.
需要設置關閉程式碼壓縮上傳, 開啟可能報錯.

這些默認都是關閉的.

微信小程式的編譯預覽及打包:

npm script

$ npm run dev:weapp
$ npm run build:weapp

或者:

$ taro build --type weapp --watch
$ taro build --type weapp

加上--watch會監聽文件修改, 去掉會對程式碼進行壓縮打包.

運行編譯命令之後就可以在微信開發者工具中預覽了. 是顯示一個Hello World.

項目結構

因為創建項目的時候用了TypeScript, 所以項目結構是這樣的:

├── dist                   編譯結果目錄
├── config                 配置目錄
|   ├── dev.js             開發時配置
|   ├── index.js           默認配置
|   └── prod.js            打包時配置
├── src                    源碼目錄
|   ├── pages              頁面文件目錄
|   |   ├── index          index頁面目錄
|   |   |   ├── index.scss index頁面樣式
|   |   |   └── index.tsx  index頁面邏輯
|   ├── app.scss           項目總通用樣式
|   ├── app.tsx            項目入口文件
|   └── index.html          
└── package.json

如果需要創建組件, 可以在src下創建component目錄來統一存放組件.

“Hello world!”就在index.tsx中.

IDE

關於IDE:
我發現用微信開發者工具是打不開這些後綴名為scsstsx的文件的.
微信開發者工具只能用來預覽.

後來用了Intellij, 是能查看文件了,
但是開始寫程式碼之後, 發現沒有自動提示, 也沒有自動格式化工具.

又下了個VS CODE:

brew cask install visual-studio-code

格式化的快捷鍵是:
Shift + Alt + F.

後來我在Text Editor設置里勾選了Format On Save.

編寫程式碼

Step 1: 靜態頁面顯示

先弄幾個數據靜態顯示一下:

export default class Index extends Component {
  config: Config = {
    navigationBarTitleText: '首頁'
  }

  constructor(props) {
    super(props)
    this.state = {
      list: ['get up', 'eat breakfast', 'study',]
    }
    inputVal: ''
  }

  render() {
    let { list, inputVal } = this.state

    return (
      <View className='index'>
        <View className='list_wrap'>
          <Text>Todo List</Text>
          {
            list.map((item, index) => {
              return <View>
                <Text>{index + 1}.{item}</Text>
              </View>
            })
          }
        </View>
      </View>
    )
  }
}

然後命令行運行:

taro build --type weapp --watch

就會直接顯示出來結果. 之後的修改也是隨時呈現.

這裡IDE報告兩個TypeScript的問題:

Property 'list' does not exist on type 'Readonly<{}>'

和:

Property 'inputVal' does not exist on type 'Index'.

按照這裡的方法修改的:

interface MyProps {
}

interface MyState {
  list: Array<string>;
  inputVal: string;
}

export default class Index extends Component<MyProps, MyState> {
//...
}

程式碼中設置值的時候調用this.setState().

Step 2: 添加和刪除項目

加上輸入框, 添加和刪除按鈕的對應方法.
完整程式碼:

interface MyProps {
}

interface MyState {
  list: Array<string>;
  inputVal: string;
}

export default class Index extends Component<MyProps, MyState> {
  config: Config = {
    navigationBarTitleText: '首頁'
  }

  constructor(props) {
    super(props)
    this.state = {
      list: ['get up', 'eat breakfast', 'study',],
      inputVal: ''
    }

  }

  addItem() {
    let { list } = this.state
    const inputVal = this.state.inputVal

    if (inputVal == '') return
    else {
      list.push(inputVal)
    }
    this.setState({
      list,
      inputVal: ''
    })
  }

  removeItem(index) {
    let { list } = this.state
    list.splice(index, 1)
    this.setState({
      list
    })
  }

  inputHandler(e) {
    this.setState({ inputVal: e.target.value })
  }

  render() {
    let { list, inputVal } = this.state

    return (
      <View className='index'>
        <Input className='input' type='text' value={inputVal} onInput={this.inputHandler.bind(this)} />
        <Text className='add' onClick={this.addItem.bind(this)}>添加</Text>
        <View className='list_wrap'>
          <Text>Todo List</Text>
          {
            list.map((item, index) => {
              return <View className='list_item'>
                <Text>{index + 1}.{item}</Text>
                <Text className='del' onClick={this.removeItem.bind(this, index)}>刪除</Text>
              </View>
            })
          }
        </View>
      </View>
    )
  }
}

Step 3: 樣式調整

用了這裡面的樣式: //juejin.im/book/5b73a131f265da28065fb1cd

然後企圖調整button的對齊. (CSS不太擅長, 請輕拍, 請指教.)

.input {
    display: inline-block;
    margin: 32px;
    border: 1px solid #666;
    width: 65%;
    vertical-align: middle;
}
.list_wrap {
    padding: 32px;
}
.list_item {
    margin: 20px 0;
}
.add,
.del {
    display: inline-block;
    width: 120px;
    height: 60px;
    margin: 0 10px;
    padding: 0 10px;
    font-size: 22px;
    line-height: 60px;
    text-align: center;
    border-radius: 10px;
    box-sizing: border-box;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    justify-content: center;
    vertical-align: middle;
}
.add {
    background-color: #5c89e4;
    color: #fff;
    border: 1px solid #5c89e4;
}
.del {
    background-color: #fff;
    color: #5c89e4;
    border: 1px solid #5c89e4;
    position: absolute;
    right: 32px;
}

Taro命令

快速生成新的頁面文件:

Taro create --name [頁面名稱] 

參考

最後, 歡迎關注微信公眾號: 聖騎士Wind
微信公眾號