国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

微信小程序模塊化開發(fā)實(shí)踐

luxixing / 1249人閱讀

摘要:前言省略準(zhǔn)備了解微信小程序是什么微信小程序官方文檔了解應(yīng)用狀態(tài)管理方案也是架構(gòu)的具體實(shí)現(xiàn)了解打包工具了解代碼轉(zhuǎn)譯工具原理大致是借助語(yǔ)法分析工具之類的將代碼解析成抽象語(yǔ)法樹再重寫成最終的代碼測(cè)試工具等等請(qǐng)根據(jù)需要選擇微信小程序目前版本的實(shí)現(xiàn)需

前言: 省略...

準(zhǔn)備

了解微信小程序是什么? 微信小程序官方文檔

了解應(yīng)用狀態(tài)管理方案: Redux, 也是Flux架構(gòu)的具體實(shí)現(xiàn)

了解Javascript打包工具: webpack

了解ES6/7代碼轉(zhuǎn)譯(transcompile)工具: Babel, 原理大致是借助語(yǔ)法分析工具(Esprima之類的), 將代碼解析成抽象語(yǔ)法樹, 再"重寫"成最終的代碼.

Javascript測(cè)試工具: jest, mocha等等, 請(qǐng)根據(jù)需要選擇.

TL;DR;

微信小程序目前版本的API實(shí)現(xiàn)需要兼顧方方面面, 所以仍然使用callback寫法, 眾所周知的Callback-Hell是傳統(tǒng)js語(yǔ)法上的歷史問(wèn)題, 但畢竟稱手的工具是開發(fā)效率的源泉. 因此筆者對(duì)當(dāng)前版本的微信小程序API做了簡(jiǎn)單的封裝 weapp.

同時(shí), 微信小程序框架本身專注于交互和UI的實(shí)現(xiàn), 并未提供內(nèi)置的狀態(tài)管理, 如果眾多的異步操作都直接在App或者Page中一一實(shí)現(xiàn), 相信寫起來(lái)會(huì)是一場(chǎng)噩夢(mèng), 而且不易于測(cè)試, 筆者又因此針對(duì)微信小程序?qū)崿F(xiàn)了一個(gè)基于Redux方案的狀態(tài)管理模塊, 用以方便的在小程序中實(shí)現(xiàn)應(yīng)用狀態(tài)管理 redux-weapp.

特別地, 微信小程序構(gòu)建(編譯)時(shí)不支持從App scope之外require文件, npm在此就不好用了. 所以, 我們需要實(shí)時(shí)build依賴到應(yīng)用本地, 在微信小程序中引用本地的modules, 對(duì)于這種構(gòu)建場(chǎng)景, 筆者認(rèn)為webpack算是最方便的方案. 大家都說(shuō)COPY到本地是最最最方便的方式~~

安裝工具和依賴模塊 下載微信小程序開發(fā)者工具

開發(fā)者工具是用nwjs模擬的環(huán)境, 實(shí)際在微信中是JavascriptCore環(huán)境, 不過(guò)不用擔(dān)心, 只是兩個(gè)不同的vm, 本質(zhì)是一樣的.

nwjs可能存在一些小bug, 寫代碼的時(shí)候注意一下就好.

下載 微信小程序開發(fā)者工具

用npm命令開始一個(gè)微信小程序項(xiàng)目
mkdir myapp
cd myapp
npm init
開始安裝必要的依賴模塊

由于除了小程序運(yùn)行時(shí)需要的模塊, 還有構(gòu)建所需要的模塊, 看起來(lái)會(huì)比較多, 不過(guò)不用擔(dān)心, 大多數(shù)都是聲明性的, 不需要你直接調(diào)用.

為了方便經(jīng)驗(yàn)少些的同學(xué)理解, 我將這些依賴分步安裝.

代碼轉(zhuǎn)譯工具, Babel

npm install --save-dev babel-cli babel-core babel-loader babel-plugin-add-module-exports babel-polyfill babel-preset-es2015 babel-preset-stage-0

有了上面這些模塊, 就可以在構(gòu)建時(shí)將ES6/7的代碼轉(zhuǎn)譯為ES5的代碼了(其實(shí)解釋器都只認(rèn)ES5).

安裝打包工具, webpack

npm install webpack --save-dev

在此, 我們只需要對(duì)代碼進(jìn)行打包, 不需要dev server和hot module replace功能, 因此只需要安裝webpack module本身, 無(wú)需安裝其他擴(kuò)展和插件.

安裝Redux

npm install redux redux-thunk --save-dev

由于在實(shí)際應(yīng)用中, 我們經(jīng)常會(huì)需要異步調(diào)用API服務(wù)器的接口, 所以需要redux-thunk這個(gè)模塊來(lái)處理 異步action.

安裝開發(fā)小程序的輔助模塊

npm install xixilive/weapp xixilive/redux-weapp --save-dev

其中, weapp模塊是對(duì)微信小程序API的wrapper, 提供了更易于使用的API, redux-weapp是基于Redux對(duì)微信小程序進(jìn)行狀態(tài)管理.

建立項(xiàng)目目錄結(jié)構(gòu)如下
myapp
 |- es6                # 源代碼
   |- myapp.js         # 在app.js文件中require此文件
 |- lib                # 存放編譯之后的js文件
 |- pages              # 小程序頁(yè)面定義
   |- projects
     |- projects.js
     |- projects.json
     |- projects.wxml
     |- projects.wxss
   ...
 |- app.js             # 小程序入口文件
 |- app.json
 |- app.wxss
 |- webpack.config.js  # webpack配置文件
編寫構(gòu)建腳本

首先得寫webpack.config.js, 這個(gè)是必須的, 由于這個(gè)構(gòu)建是為了本地化微信小程序的依賴, 因此只處理js文件, 若需要打包其他諸如css, image等資源, 請(qǐng)讀者自行研究. 實(shí)際上, 微信小程序包有1MB的上限.

// webpack.config.js

var path = require("path"), webpack = require("webpack")

var jsLoader = {
  test: /.js$/, // 你也可以用.es6做文件擴(kuò)展名, 然后在這里定義相應(yīng)的pattern
  loader: "babel",
  query: {
    // 代碼轉(zhuǎn)譯預(yù)設(shè), 并不包含ES新特性的polyfill, polyfill需要在具體代碼中顯示require
    presets: ["es2015", "stage-0"]
  },
  // 指定轉(zhuǎn)譯es6目錄下的代碼
  include: path.join(__dirname, "es6"),
  // 指定不轉(zhuǎn)譯node_modules下的代碼
  exclude: path.join(__dirname, "node_modules")
}

module.exports = {
  // sourcemap 選項(xiàng), 建議開發(fā)時(shí)包含sourcemap, production版本時(shí)去掉(節(jié)能減排)
  devtool: null,

  // 指定es6目錄為context目錄, 這樣在下面的entry, output部分就可以少些幾個(gè)`../`了
  context: path.join(__dirname, "es6"),

  // 定義要打包的文件
  // 比如: `{entry: {out: ["./x", "./y","./z"]}}` 的意思是: 將x,y,z等這些文件打包成一個(gè)文件,取名為: out
  // 具體請(qǐng)參看webpack文檔
  entry: {
    myapp: "./myapp"
  },

  output: {
    // 將打包后的文件輸出到lib目錄
    path: path.join(__dirname, "lib"),

    // 將打包后的文件命名為 myapp, `[name]`可以理解為模板變量
    filename: "[name].js",

    // module規(guī)范為 `umd`, 兼容commonjs和amd, 具體請(qǐng)參看webpack文檔
    libraryTarget: "umd"
  },

  module: {
    loaders: [jsLoader]
  },

  resolve: {
    extensions: ["", ".js"],
    // 將es6目錄指定為加載目錄, 這樣在require/import時(shí)就會(huì)自動(dòng)在這個(gè)目錄下resolve文件(可以省去不少../)
    modulesDirectories: ["es6", "node_modules"]
  },

  plugins: [
    new webpack.NoErrorsPlugin(),

    // 通常會(huì)需要區(qū)分dev和production, 建議定義這個(gè)變量
    // 編譯后會(huì)在global中定義`process.env`這個(gè)Object
    new webpack.DefinePlugin({
      "process.env": {
        "NODE_ENV": JSON.stringify("development")
      }
    })
  ]
}
定義npm命令

test 筆者比較喜歡jest, 所以在此就用jest做范例了.

// package.json

"scripts": {
  "pretest": "eslint es6", //推薦進(jìn)行靜態(tài)檢查
  "test": "jest",
  ...
},
...,
// jest允許在package.json中定義配置
"jest": {
  "automock": false,
  "bail": true,
  "transform": {
    ".js": "/node_modules/babel-jest" //用babel轉(zhuǎn)譯
  },
  "testPathDirs": [
    "/__tests__/"
  ],
  "testRegex": ".test.js$",
  "unmockedModulePathPatterns": [
    "/node_modules/"
  ],
  "testPathIgnorePatterns": [
    "/node_modules/"
  ]
}

build 這里就是構(gòu)建的命令了, 成敗在此一舉 :)

// package.json

"scripts": {
  ...,
  // 帶上watch選項(xiàng), 實(shí)時(shí)編譯修改, 由于小程序開發(fā)工具也監(jiān)視應(yīng)用文件的修改, 所以es6目錄下的js文件修改, 將導(dǎo)致小程序開發(fā)工具自動(dòng)重新加載
  "build": "webpack --watch --progress --colors --config webpack.config.js"
},
寫應(yīng)用代碼

總算進(jìn)入正題了(工欲善其事,...), 借助上述的 weapp 和 redux-weapp, 希望你會(huì)感到很舒服~~.

在這個(gè)范例(myapp)中, 我們目標(biāo)是去查詢 github/octokit 的開源項(xiàng)目, 并顯示在小程序中.

建議不了解Redux的讀者先去快速了解一下(2 hours) Getting started with Redux - from egghead

myapp模塊

定義store: /es6/store.js

這里只是簡(jiǎn)單的范例, 實(shí)際中會(huì)有比較復(fù)雜的store shape, 需要引入更多的middleware來(lái)處理動(dòng)作和狀態(tài)的變化.

// /es6/store.js

import {createStore, applyMiddleware, bindActionCreators} from "redux"
import thunk from "redux-thunk"
import reducers from "./reducers"

export default function(initState = {}){
  return createStore(
    reducers,
    initState,
    applyMiddleware(thunk)
  )
}

定義reducers: /es6/reducers.js

Reducer就是處理因Store dispatch actions時(shí)發(fā)生的狀態(tài)變化的function, 參數(shù)總是為(state, action)

// /es6/reducers.js
import { combineReducers } from "redux"

// 處理projects邏輯
const projects = (state = [], action) => {
  switch (action.type) {
    case "PROJECTS_LOADED":
      return state.concat[action.payload]
    //other cases
  }

  return state
}

// 將多個(gè)reducer合并起來(lái)
// 這里就可以看出store的結(jié)構(gòu)了, 是不是很 predictable ?
export default combineReducers({
  projects
})

定義actions: /es6/actions.js

Action通常是個(gè)Plain Object, 總是被Store dispatch, 描述了"發(fā)生了什么, 結(jié)果是什么"的邏輯

// /es6/actions.js

import {weapp} from "weapp"

// 更好的方法是定義一個(gè)api module, 來(lái)處理網(wǎng)絡(luò)請(qǐng)求
const http = weapp.Http("https://api.github.com")

// 這是一個(gè)異步action, redux-thunk會(huì)處理返回值為Function的action(可以編入繞口令大全了~~)
export const loadProjects = (org) => {
  return (dispatch) => {
    http.get(`/orgs/${org}/repos`).then(response => {
      // 讓store去廣播"PROJECTS_LOADED"這件事情發(fā)生了
      dispatch({
        type: "PROJECTS_LOADED",
        payload: response
      })
    })
  }
}

myapp模塊入口: /es6/myapp.js

// /es6/myapp.js
import {bindActionCreators} from "redux"
import {weapp} from "weapp"
import connect from "redux-weapp"
import store from "./store"
import actions from "./actions"

export {
  weapp,
  connect,
  bindActionCreators,
  store,
  actions
}
小程序模塊

入口文件: app.jsapp.json

// /app.js
App({
  // 方便起見, 這里不做任何life-cycle處理
})

app.json

{
  "pages": [
    "pages/projects/projects"
  ],
  "window": {
    "navigationBarTitleText": "Orchid"
  },
  "networkTimeout": {
    "request": 10000,
    "downloadFile": 10000
  },
  "debug": true
}

頁(yè)面邏輯: projects.js

如上定義, 小程序的啟動(dòng)頁(yè)面是projects

// /pages/projects/projects.js

// 引入編譯過(guò)的modules
import {
  weapp,
  connect,
  bindActionCreators,
  store,
  actions
} from "../../lib/app"

// 標(biāo)準(zhǔn)Page定義Object
const config = {
  data: {
    projects: [] //for init-render
  },

  onReady(){
    // 哪里來(lái)的 loadProjects? 往下看
    this.loadProjects("octokit")
  },

  onStateChange(nextState){
    this.setData({projects: nextState})
  }
}

// connect store with page
const page = connect.Page(
  store, // required
  // 這個(gè)頁(yè)面只關(guān)注projects變化
  (state) => ({projects: state.projects}),

  // 將Action定義與Store.dispatch binding在一起, 這樣就是一個(gè)可以發(fā)起對(duì)github API的請(qǐng)求了
  (dispatch) => {
    return {
      loadProjects: bindActionCreators(actions.loadProjects, dispatch)
    }
  }
)

// 啟動(dòng)被connect過(guò)的頁(yè)面
Page(page(config))

頁(yè)面UI: projects.wxml


  {{project.name}}
后記

范例代碼未實(shí)際運(yùn)行, 僅用以表示開發(fā)步驟, 我會(huì)盡快把這個(gè)范例實(shí)現(xiàn)完整, 放到github上.

最后, 謝謝您耐心閱讀至此!

參考

https://github.com/nwjs/nw.js...

http://redux.js.org

https://webpack.github.io

https://facebook.github.io/je...

https://babeljs.io

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/81085.html

相關(guān)文章

  • 微信小程開發(fā)最佳實(shí)踐

    摘要:于是,我重新思考了下,最佳的微信小程序開發(fā)實(shí)踐應(yīng)該是無(wú)痛的,且舒服的,無(wú)痛的是指在小程序的飛速發(fā)展變更中,我們不用重復(fù)的浪費(fèi)學(xué)習(xí)第三方框架和原生框架。以上,便可以在微信小程序中使用了。 weapp-starter 微信小程序開發(fā)最佳實(shí)踐 項(xiàng)目地址 為什么會(huì)有這個(gè) repo 在小程序之初便開發(fā)應(yīng)用了,現(xiàn)在小程序的開發(fā)也越來(lái)越成熟了,完善了很多的API、組件、架構(gòu)等,社區(qū)也由原來(lái)的零星點(diǎn)點(diǎn)...

    Developer 評(píng)論0 收藏0
  • 前端資源系列(3)-微信小程開發(fā)資源匯總

    摘要:微信小程序應(yīng)用號(hào)開發(fā)資源匯總文檔工具教程代碼插件組件文檔從搭建一個(gè)微信小程序開始小程序開發(fā)文檔小程序設(shè)計(jì)指南工具小程序開發(fā)者工具官方支持微信小程序?qū)崟r(shí)預(yù)覽的支持的微信小程序組件化開發(fā)框架轉(zhuǎn)在線工具小程序云端增強(qiáng)社區(qū)微信小程序 微信(小程序or應(yīng)用號(hào))開發(fā)資源匯總-文檔-工具-教程-代碼-插件-組件 文檔 從搭建一個(gè)微信小程序開始 小程序開發(fā)文檔 小程序設(shè)計(jì)指南 工具 小程序開發(fā)者...

    paney129 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<