Taro微信小程序開發(fā)

一.什么是taro?

Taro 是一套遵循 React 語法規(guī)范的 多端開發(fā) 解決方案煌寇。通過一套react的代碼焕蹄,就可以分別編譯出微信小程序、H5唧席、支付寶小程序擦盾。。淌哟。
我根據(jù)taro redux模板創(chuàng)建了一套自己寫的H5種子項(xiàng)目迹卢,大家可以一起學(xué)習(xí),項(xiàng)目地址:https://github.com/WangxinsHub/taro-seed

二.如何安裝taro徒仓?

1.首先全局安裝taro命令行:

$ npm install -g @tarojs/cli

$ yarn global add @tarojs/cli

2.創(chuàng)建taro種子項(xiàng)目

$ taro init myApp


創(chuàng)建redux模板

3.編譯taro腐碱,在創(chuàng)建的種子項(xiàng)目中,package文件如下:


"scripts": {

"build:weapp": "taro build --type weapp",//打包小程序

"build:h5": "taro build --type h5", //打包H5

"dev:weapp": "npm run build:weapp -- --watch",//編譯小程序

"dev:h5": "npm run build:h5 -- --watch",//編譯H5

},

三、開發(fā)前注意

小程序工具:

需要設(shè)置關(guān)閉 ES6 轉(zhuǎn) ES5 功能症见,開啟可能報(bào)錯(cuò)

需要設(shè)置關(guān)閉上傳代碼時(shí)樣式自動(dòng)補(bǔ)全喂走,開啟可能報(bào)錯(cuò)

需要設(shè)置關(guān)閉代碼壓縮上傳,開啟可能報(bào)錯(cuò)

四谋作、項(xiàng)目說明

taro推薦目錄.png

我開發(fā)中的目錄.png

1.dist是編譯(dev/build)結(jié)果目錄

2.config配置目錄

index.js(默認(rèn)配置)

const path  = require('path')
const config = {
  projectName: 'Taro-time-bus',
  date: '2019-1-8',
  designWidth: 750,//設(shè)計(jì)稿以 iPhone6 750px 作為設(shè)計(jì)尺寸標(biāo)準(zhǔn)芋肠。
  //目前 Taro 支持 750、 640 遵蚜、 828 三種尺寸設(shè)計(jì)稿帖池,他們的換算規(guī)則如下:
  deviceRatio: {
    '640': 2.34 / 2,
    '750': 1,
    '828': 1.81 / 2
  },
  // 項(xiàng)目源碼目錄
  sourceRoot: 'src',
  // 項(xiàng)目產(chǎn)出目錄
  outputRoot: 'dist',
  // 通用插件配置
  plugins: {
    //plugins 用來設(shè)置一些各個(gè)端通用的編譯過程配置,例如 babel 配置吭净,JS/CSS 壓縮配置等睡汹。
    babel: {
      sourceMap: true,
      presets: ['env'],
      plugins: ['transform-decorators-legacy', 'transform-class-properties', 'transform-object-rest-spread']
    }
    /*
    //設(shè)置打包過程中的 JS 代碼壓縮
    uglify: {
      enable: true,
      config: {
        // 配置項(xiàng)同 https://github.com/mishoo/UglifyJS2#minify-options
      }
    },
    //設(shè)置打包過程中的 CSS 代碼壓縮
    csso: {
      enable: true,
      config: {
        // 配置項(xiàng)同 https://github.com/css/csso#minifysource-options
      }
    }*/
  },
  // 全局變量設(shè)置
  defineConstants: {
    context:{
      iconPath:'xxx'
    }
  },
  alias: {
    '@components': path.resolve(__dirname,'../src/components'),
    '@icons': path.resolve(__dirname,'../src/icons'),
    '@src': path.resolve(__dirname,'../src/'),
    '@utils': path.resolve(__dirname, '..', 'src/utils')
  },
  weapp: {
    //小程序編譯過程的相關(guān)配置。
    compile: {
      compressTemplate: true,//決定小程序打包時(shí)是否需要壓縮 wxml
    },
    module: {
      postcss: {
        autoprefixer: {
          enable: true,
          config: {
            browsers: [
              'last 3 versions',
              'Android >= 4.1',
              'ios >= 8'
            ]
          }
        },
        pxtransform: {
          enable: true,
          config: {
            onePxTransform: true, //設(shè)置 1px 是否需要被轉(zhuǎn)換
            unitPrecision: 5,//REM 單位允許的小數(shù)位寂殉。
            selectorBlackList: [],//黑名單里的選擇器將會(huì)被忽略囚巴。
            replace: true,//直接替換而不是追加一條進(jìn)行覆蓋。
            mediaQuery: false,//允許媒體查詢里的 px 單位轉(zhuǎn)換
            minPixelValue: 0//設(shè)置一個(gè)可被轉(zhuǎn)換的最小 px 值
          }
        },
        url: {
          enable: true,
          config: {
            limit: 10240 // 設(shè)定轉(zhuǎn)換尺寸上限
          }
        },
        cssModules: {
          enable: false, // 默認(rèn)為 false友扰,如需使用 css modules 功能彤叉,則設(shè)為 true
          config: {
            namingPattern: 'module', // 轉(zhuǎn)換模式,取值為 global/module
            generateScopedName: '[name]__[local]___[hash:base64:5]'
          }
        }
      }
    }
  },
  h5: {
    devServer: {
      port: 10086
    },
    publicPath: '/', //設(shè)置輸出解析文件的目錄焕檬。
    staticDirectory: 'static',//h5 編譯后的靜態(tài)文件目錄姆坚。
    esnextModules: ['taro-ui'],//配置需要額外的編譯的源碼模塊,比如taro-ui:
    miniCssExtractPluginOption: {
      filename: 'css/[name]/[hash].css',
      chunkFilename: 'css/[name]/[hash].css'
    },
    module: {
      postcss: {
        autoprefixer: {
          enable: true,
          config: {
            browsers: [
              'last 3 versions',
              'Android >= 4.1',
              'ios >= 8'
            ]
          }
        },
        cssModules: {
          enable: false, // 默認(rèn)為 false实愚,如需使用 css modules 功能兼呵,則設(shè)為 true
          config: {
            namingPattern: 'module', // 轉(zhuǎn)換模式,取值為 global/module
            generateScopedName: '[name]__[local]___[hash:base64:5]'
          }
        }
      }
    }
  }
}

module.exports = function (merge) {
  if (process.env.NODE_ENV === 'development') {
    return merge({}, config, require('./dev'))
  }
  return merge({}, config, require('./prod'))
}

dev.js

module.exports = {
  env: {
    NODE_ENV: '"development"',
    API_HOSTNAME:JSON.stringify('https://appdev.ibuscloud.com'),//test環(huán)境地址
  },
  defineConstants: {
  },
  weapp: {
  },
  h5: {}
}

3.入口文件為 app.js

import '@tarojs/async-await'
import Taro, { Component } from '@tarojs/taro'
import { Provider } from '@tarojs/redux'
import 'taro-ui/dist/style/index.scss' // 全局引入一次即可

import Index from './pages/index'

import configStore from './store'

import './app.less'

// 如果需要在 h5 環(huán)境中開啟 React Devtools
// 取消以下注釋:
// if (process.env.NODE_ENV !== 'production' && process.env.TARO_ENV === 'h5')  {
//   require('nerv-devtools')
// }

const store = configStore()

class App extends Component {

  config = {
    pages: [
      'pages/index/index',
      'pages/search/index',
      'pages/lineDetail/index',
      'pages/page2/index'
    ],
    "permission": {
      "scope.userLocation": {
        "desc": "你的位置信息將用于小程序位置接口的效果展示"
      }
    },
    window: {
      backgroundTextStyle: 'light',
      navigationBarBackgroundColor: '#fff',
      navigationBarTitleText: 'WeChat',
      navigationBarTextStyle: 'black'
    }
  }

  componentDidMount () {}

  componentDidShow () {
    //獲取用戶位置腊敲,TODO:H5
    Taro.getLocation().then(data=>{
      console.log(data)
      const {latitude,longitude} = data ;
      Taro.setStorageSync('userLat', latitude);
      Taro.setStorageSync('userLng', longitude);
    })
  }

  componentDidHide () {}

  componentCatchError () {}

  componentDidCatchError () {}

  // 在 App 類中的 render() 函數(shù)沒有實(shí)際作用
  // 請(qǐng)勿修改此函數(shù)
  render () {
    return (
      <Provider store={store}>
        <Index />
      </Provider>
    )
  }
}

Taro.render(<App />, document.getElementById('app'))

1??其中config主要參考微信小程序的全局配置而來击喂,在編譯成小程序時(shí),這一部分配置將會(huì)被抽離成 app.json碰辅,而編譯成其他端懂昂,亦會(huì)有其他作用。
頁面路由在此配置没宾,頁面背景色導(dǎo)航欄等也在此設(shè)置
2??app.js的生命周期凌彬、頁面與組件的生命周期:
而且由于入口文件繼承自 Component 組件基類,它同樣擁有組件生命周期循衰,但因?yàn)槿肟谖募奶厥庑圆玻纳芷诓?em>不完整,如下

image.png

3??普通頁面生命周期與component一致
image.png

小程序?qū)S械姆椒ǎ海℉5中暫不支持)
image.png

4??組件Taro 的組件同樣是繼承自 Component 組件基類会钝,與頁面類似伐蒋,組件也必須包含一個(gè) render 函數(shù),返回 JSX 代碼。 比頁面多了一個(gè)componentWillReceiveProps先鱼。

注意 : 組件的 constructor 與 render 提前調(diào)用俭正,所以componentWillMount這個(gè)生命周期有一個(gè)滯后性,不可以直接在render中用路由得來的數(shù)據(jù)

render () {
  // 在 willMount 之前無法拿到路由參數(shù)
  const abc = this.$router.params.abc
  return <Custom adc={abc} />
}

?

// 正確寫法
componentWillMount () {
  const abc = this.$router.params.abc
  this.setState({
    abc
  })
}
render () {
  // 增加一個(gè)兼容判斷
  return this.state.abc && <Custom adc={abc} />
}

?
由于微信小程序里頁面在 onLoad 時(shí)才能拿到頁面的路由參數(shù)焙畔,而頁面 onLoad 前組件都已經(jīng) attached 了掸读。因此頁面的 componentWillMount 可能會(huì)與預(yù)期不太一致。

五闹蒜、開發(fā)中的問題

1.靜態(tài)資源的引入

1??通過ES6的import引用圖片寺枉、js抑淫、等文件(暫不支持svg)绷落,而且不需要安裝任何 loader。
2??可以先上傳到服務(wù)器始苇,然后引用服務(wù)器的地址(在less中background用的多一點(diǎn))

全局原始app.less 只會(huì)影響到頁面級(jí)別的文件砌烁,組件的獲取不到全局的樣式
可以同過@import 讓組件獲得app.less全局樣式

@import "../../app";

2.jsx的支持程度:

<View {...this.props} />
 
<View {...props} />
 
<Custom {...props} />

以上是錯(cuò)誤寫法

3.組件化 & props &state

1??使用 PropTypes 檢查類型

Greeting.propTypes = {
  name: PropTypes.string
};

2??給組件設(shè)置 defaultProps

3??組件傳遞函數(shù)屬性名以 on 開頭

4??當(dāng)組件傳入jsx的時(shí)候必須用render開頭,在小程序中其實(shí)是通過slot插槽來實(shí)現(xiàn)的,所以和this.props.children一樣斋攀, this.props.children && this.props.children到腥、this.props.children[0] 在 Taro 中都是非法的。且組合只能傳入單個(gè) JSX 元素萌业,不能傳入其它任何類型坷襟。當(dāng)你需要進(jìn)行一些條件判斷或復(fù)雜邏輯操作的時(shí)候,可以使用一個(gè) Block 元素包裹住生年,然后在 Block 元素的里面填充其它復(fù)雜的邏輯婴程。

state:

5??state this.state 和 props 一定是異步更新的,所以你不能在 setState 馬上拿到 state 的值

6??不要在 stateprops 上用同名的字段抱婉,因?yàn)檫@些被字段在微信小程序中都會(huì)掛在 data
7??盡量避免在 componentDidMount 中調(diào)用 this.setState 因?yàn)樵?componentDidMount 中調(diào)用 this.setState 會(huì)導(dǎo)致觸發(fā)更新 (盡量避免档叔,可以componentWillMount 中處理)
不要在 componentWillUpdate/componentDidUpdate/render 中調(diào)用 this.setState

5.事件

事件類型參照微信小程序https://developers.weixin.qq.com/miniprogram/dev/framework/view/wxml/event.html

6.路由

1??傳參:

Taro.navigateTo({
  url: '/pages/page/path/name?id=2&type=test'
})

接收:this.$router.params

2??預(yù)加載傳參
在微信小程序中,從調(diào)用 Taro.navigateTo蒸绩、Taro.redirectTo 或 Taro.switchTab 后衙四,到頁面觸發(fā) componentWillMount 會(huì)有一定延時(shí)。因此一些網(wǎng)絡(luò)請(qǐng)求可以提前到發(fā)起跳轉(zhuǎn)前一刻去請(qǐng)求侵贵。


image.png

傳參:

this.$preload({
  x: 1,
  y: 2
})
Taro.navigateTo({ url: '/pages/B/B' })

(也能夠繞過 componentWillMount 延時(shí))

接收componentWillMount () {
  console.log('preload: ', this.$router.preload)
}

7異步編程 以及 接口請(qǐng)求

$ yarn add @tarojs/async-await
import '@tarojs/async-await'
異步dispatch届搁,action.js:

import '@tarojs/async-await'
import {
  ADD,
  MINUS,
  ASYNC,
  ASYNC_BEFORE
} from './action-type';
import Http from '../../api/Server'
import Url from '../../api/url';

export const add = () => {
  return {
    type: ADD
  }
}
export const minus = () => {
  return {
    type: MINUS
  }
}

export const asyncAdd = (params) => {
  // 返回函數(shù),異步dispatch
  return async dispatch => {
    try{
      dispatch({
        type: ASYNC_BEFORE,
      })
      let result = await Http.request('post',Url.lineRecommendQuery,params);
      // 如果不成功,則將不成功的信息打印出來
      if(result){
        if(!result.success) console.error(result.message);
        dispatch({
          type: ASYNC,
          response: result,
        })
      }
    }catch(err){
      console.error(err);
    }
  }
}

Http 請(qǐng)求工具類:api.js

import Taro from '@tarojs/taro'

class Http {
  constructor(){
    const HOSTNAME = process.env.API_HOSTNAME
    this.url={
    
   }
  }
  request(method = 'post', url, params) {
    console.log(process.env.TARO_ENV)
    Taro.showNavigationBarLoading();
    return new Promise((resolve, reject) => {
      Taro.request({
        url,
        method,
        data: params,
        header: {
          'Content-Type': 'application/x-www-form-urlencoded',
          'Accept': '*/*'
        }
      }).then(res => {
        Taro.hideNavigationBarLoading()
        resolve(typeof res.data === 'object' ? res.data : JSON.parse(res.data))
      }, err => {
        Taro.hideNavigationBarLoading()
        reject(err)
      })
    })
  }
}

export default new Http();
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末卡睦,一起剝皮案震驚了整個(gè)濱河市宴胧,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌表锻,老刑警劉巖恕齐,帶你破解...
    沈念sama閱讀 221,888評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異瞬逊,居然都是意外死亡显歧,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,677評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門确镊,熙熙樓的掌柜王于貴愁眉苦臉地迎上來士骤,“玉大人,你說我怎么就攤上這事蕾域】郊。” “怎么了?”我有些...
    開封第一講書人閱讀 168,386評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵旨巷,是天一觀的道長巨缘。 經(jīng)常有香客問我,道長采呐,這世上最難降的妖魔是什么若锁? 我笑而不...
    開封第一講書人閱讀 59,726評(píng)論 1 297
  • 正文 為了忘掉前任,我火速辦了婚禮斧吐,結(jié)果婚禮上又固,老公的妹妹穿的比我還像新娘。我一直安慰自己会通,他們只是感情好口予,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,729評(píng)論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著涕侈,像睡著了一般沪停。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上裳涛,一...
    開封第一講書人閱讀 52,337評(píng)論 1 310
  • 那天木张,我揣著相機(jī)與錄音,去河邊找鬼端三。 笑死舷礼,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的郊闯。 我是一名探鬼主播妻献,決...
    沈念sama閱讀 40,902評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼蛛株,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了育拨?” 一聲冷哼從身側(cè)響起谨履,我...
    開封第一講書人閱讀 39,807評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎熬丧,沒想到半個(gè)月后笋粟,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,349評(píng)論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡析蝴,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,439評(píng)論 3 340
  • 正文 我和宋清朗相戀三年害捕,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片闷畸。...
    茶點(diǎn)故事閱讀 40,567評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡尝盼,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出腾啥,到底是詐尸還是另有隱情东涡,我是刑警寧澤,帶...
    沈念sama閱讀 36,242評(píng)論 5 350
  • 正文 年R本政府宣布倘待,位于F島的核電站,受9級(jí)特大地震影響组贺,放射性物質(zhì)發(fā)生泄漏凸舵。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,933評(píng)論 3 334
  • 文/蒙蒙 一失尖、第九天 我趴在偏房一處隱蔽的房頂上張望啊奄。 院中可真熱鬧,春花似錦掀潮、人聲如沸菇夸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,420評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽庄新。三九已至,卻和暖如春薯鼠,著一層夾襖步出監(jiān)牢的瞬間择诈,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,531評(píng)論 1 272
  • 我被黑心中介騙來泰國打工出皇, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留羞芍,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,995評(píng)論 3 377
  • 正文 我出身青樓郊艘,卻偏偏與公主長得像荷科,于是被迫代替她去往敵國和親唯咬。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,585評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容