最近在研究小程序這方面的東西菊霜,使用到了京東基于
React
的小程序開(kāi)發(fā)框架Taro
,相比mpvue
和uni-app
這兩個(gè)框架來(lái)說(shuō)脊另,Taro
顯得更優(yōu)雅导狡,更穩(wěn)重,大廠在迭代偎痛,就是不一樣旱捧,一句話(huà) ,就是坑少一點(diǎn)~
前置知識(shí)
看本篇教程前需要你掌握 dva
,React Hooks
,Redux
,還有小程序的開(kāi)發(fā)流程看彼。希望你知其然廊佩,并知其所以然。如果你不具備以上任意一點(diǎn)靖榕,建議先停下來(lái)标锄,下面我給出地址,先自行學(xué)習(xí)之后再過(guò)來(lái)看我這篇文章 茁计。
React-用于構(gòu)建用戶(hù)界面的 JavaScript 庫(kù)
React Hooks-更優(yōu)雅的React應(yīng)用書(shū)寫(xiě)方式
正式開(kāi)始
安裝 Taro腳手架
# 使用 npm 安裝 CLI
$ npm install -g @tarojs/cli
# OR 使用 yarn 安裝 CLI
$ yarn global add @tarojs/cli
# OR 安裝了 cnpm料皇,使用 cnpm 安裝 CLI
$ cnpm install -g @tarojs/cli
因?yàn)槲译娔X安裝了 cnpm
鏡像源,所以下文我都會(huì)用 cnpm
腳手架完成后使用腳手架初始化一個(gè)新項(xiàng)目
在你需要建立項(xiàng)目的文件夾打開(kāi) CMD
taro init test//我們演示的項(xiàng)目名叫test
然后跟著流程走星压,這邊為了減少你的學(xué)習(xí)成本践剂,建議不要選擇 Typescript
,css選擇less
,模版選擇默認(rèn)模版。
最后成功之后娜膘,用你的編輯器打開(kāi)test目錄逊脯。
你的目錄結(jié)構(gòu)跟我的應(yīng)該是一樣的
先刪除 ./src/pages
下面的 index
文件夾。
然后命令行在test
目錄打開(kāi)竣贪,安裝我們需要用的擴(kuò)展
cnpm install --save @tarojs/async-await //沒(méi)想到吧 在Taro里面使用 async和 await 需要安裝這個(gè)擴(kuò)展
cnpm install --save redux @tarojs/redux @tarojs/redux-h5 redux-thunk redux-logger //Redux全家桶
cnpm install --save dva-core dva-loading //dva
cnpm install --save taro-axios //在Taro里面使用axios 需要安裝他
這四個(gè)命令安裝完之后军洼,打開(kāi)./src
目錄 ,新建兩個(gè)文件夾 演怎,一個(gè)叫 utils
一個(gè)叫 models
注意這兩個(gè)文件夾應(yīng)該跟你的 pages
文件夾同級(jí)匕争。
在 utils
文件夾下面新建文件 dva.js
寫(xiě)上下面的內(nèi)容 注冊(cè)dva
import { create } from 'dva-core';
import { createLogger } from 'redux-logger';
import createLoading from 'dva-loading';
let app;
let store;
let dispatch;
function createApp(opt) {
// redux日志
// opt.onAction = [createLogger()];
app = create(opt);
app.use(createLoading({}));
if (!global.registered) opt.models.forEach(model => app.model(model));
global.registered = true;
app.start();
store = app._store;
app.getStore = () => store;
dispatch = store.dispatch;
app.dispatch = dispatch;
return app;
}
export default {
createApp,
getDispatch() {
return app.dispatch;
}
}
在 utils
文件夾下面新建文件 request.js
寫(xiě)上下面的內(nèi)容 封裝一個(gè)簡(jiǎn)單的axios
實(shí)際你的項(xiàng)目中可能不一樣
import axios from "taro-axios";
const baseURL = `https://blog.xiaohuwei.cn`
const service = axios.create({
baseURL: baseURL,
withCredentials: true,
timeout: 300000
});
service.interceptors.response.use(
response => {
return response.data;
},
error => {
return Promise.reject(error)
})
export default service
在 models
文件夾下面新建文件 models.js
寫(xiě)上下面的內(nèi)容 連接你每個(gè)頁(yè)面的倉(cāng)庫(kù)注冊(cè)到全局
import index from '../pages/index/model';
export default [index];
你會(huì)發(fā)現(xiàn)我們剛才吧 index
文件夾已經(jīng)刪除了 ,這里先這樣寫(xiě)爷耀,后面我在做說(shuō)明甘桑。
下一步 修改 ./src/app.jsx
作用就是把我們所有的倉(cāng)庫(kù)連接進(jìn)來(lái) 方便你學(xué)習(xí) 下面給出修改后的全部代碼
import '@tarojs/async-await'
import Taro, { Component } from '@tarojs/taro'
import Index from './pages/index'
import dva from './utils/dva';
import models from './models/models';
import { Provider } from '@tarojs/redux';
import './app.less'
const dvaApp = dva.createApp({
initialState: {},
models: models,
});
const store = dvaApp.getStore();
class App extends Component {
config = {
pages: [
'pages/index/index'
],
window: {
backgroundTextStyle: 'light',
navigationBarBackgroundColor: '#fff',
navigationBarTitleText: 'WeChat',
navigationBarTextStyle: 'black'
}
}
componentDidMount() { }
componentDidShow() { }
componentDidHide() { }
componentDidCatchError() { }
// 在 App 類(lèi)中的 render() 函數(shù)沒(méi)有實(shí)際作用
// 請(qǐng)勿修改此函數(shù)
render() {
return (
<Provider store={store}>
<Index />
</Provider>
)
}
}
Taro.render(<App />, document.getElementById('app'))
最后一步
在你項(xiàng)目 根目錄 ,為了跟我保持一致,希望你在根目錄新建一個(gè)叫 page.js的文件
這個(gè)文件我們用來(lái)自動(dòng)生成新頁(yè)面跑杭,包含新頁(yè)面的 ui層
service層
和 model層
方便快速開(kāi)發(fā)铆帽。內(nèi)容如下
/**
* pages模版快速生成腳本,執(zhí)行命令 npm run temp `文件名`
*/
const fs = require('fs');
const dirName = process.argv[2];
if (!dirName) {
console.log('文件夾名稱(chēng)不能為空!');
console.log('示例:npm run temp test');
process.exit(0);
}
// 頁(yè)面模版
const indexTep = `import Taro,{useEffect} from '@tarojs/taro';
import { View,Text } from '@tarojs/components';
import { connect } from '@tarojs/redux';
import './index.less';
const ${titleCase(dirName)} = props =>{
const {${dirName},loading} = props;
useEffect(() => {
console.log(props)
}, [])
return (
<View className="${dirName}-page">
<Text>正如你所見(jiàn)這是你的${dirName}頁(yè)面</Text>
</View>
)
}
${titleCase(dirName)}.config = {
navigationBarTitleText: '${dirName}'
}
//全局樣式繼承 你可以關(guān)掉
${titleCase(dirName)}.options = {
addGlobalClass: true
}
export default connect(
({
${dirName},
loading
})=>({
${dirName},
loading
}))(${titleCase(dirName)})
`;
// less文件模版
const lessTep = `
.${dirName}-page {
}
`;
// model文件模版
const modelTep = `import * as ${dirName}Api from './service';
export default {
namespace: '${dirName}',
state: {
keai:'測(cè)試數(shù)據(jù)666'
},
effects: {
* effectsDemo(_, { call, put }) {
const { status, data } = yield call(${dirName}Api.demo, {});
if (status === 'ok') {
yield put({ type: 'save',
payload: {
topData: data,
} });
}
},
},
reducers: {
save(state, { payload }) {
return { ...state, ...payload };
},
},
};
`;
// service頁(yè)面模版
const serviceTep = `import Request from '../../utils/request';
export const demo = (data) => {
return Request({
url: '路徑',
method: 'POST',
data,
});
};
`;
fs.mkdirSync(`./src/pages/${dirName}`); // mkdir $1
process.chdir(`./src/pages/${dirName}`); // cd $1
fs.writeFileSync('index.js', indexTep);
fs.writeFileSync('index.less', lessTep);
fs.writeFileSync('model.js', modelTep);
fs.writeFileSync('service.js', serviceTep);
console.log(`模版${dirName}已創(chuàng)建,請(qǐng)手動(dòng)按照格式增加到./src/models`);
function titleCase(str) {
const array = str.toLowerCase().split(' ');
for (let i = 0; i < array.length; i++) {
array[i] = array[i][0].toUpperCase() + array[i].substring(1, array[i].length);
}
const string = array.join(' ');
return string;
}
process.exit(0);
完成之后 去 package.json
里面的 scripts
添加一條 命令 "temp": "node page.js"
如果你能夠走到這一步 德谅,說(shuō)明你已經(jīng)成功了 锄贼,跟我的目錄結(jié)構(gòu) 對(duì)照一下
命令行在你的項(xiàng)目目錄打開(kāi),我們來(lái)使用 腳本生成第一個(gè)頁(yè)面 index
npm run temp index
你會(huì)發(fā)現(xiàn)你的./src/pages
目錄下多了 index 文件夾 并且文件夾下面已經(jīng)為你初始化好了所有你需要的文件女阀,但是并沒(méi)有結(jié)束宅荤。
就是上文提到的 ,每次新建一個(gè)頁(yè)面都需要去 ./src/models/models.js
手動(dòng) 按照我給你的格式引入一次浸策,因?yàn)槲疫@個(gè)組件叫 index冯键,所以我給你的默認(rèn)就是 index,所以我這里不用改,你做項(xiàng)目的時(shí)候庸汗,是需要手動(dòng)加的惫确。
試試效果!
npm run dev:weapp
好啦蚯舱,所有的都完成啦改化,開(kāi)始開(kāi)發(fā)你的小程序吧!~
說(shuō)下 Taro的注意事項(xiàng)
當(dāng)你 使用到了 圖片這些靜態(tài)資源的時(shí)候 枉昏,需要使用 import
的語(yǔ)法引用陈肛。
如果你想看完整代碼 移步