IONIC介紹
發現國內前端圈里面,現在知道IONIC的人已經很少了,但畢竟這東西也是一門不錯的移動端開發技術,感覺可能大多數人對於新技術的追求和嘗試,讓這個技術看起來地位略微尷尬。
但是,毫無疑問,這門技術,在全球還是相對比較流行的。
IONIC是什么?如果在利用前端技術做手機app的起步階段,大家大概會聽到phonegap、Xamarin。
其中Xamarin是基於C#的一套移動開發框架,當然,現如今團隊已經被微軟收購,生命力看起來也並不算多頑強,喜歡C#的人可能會用到,但前端同事估計很難去接觸。
而phonegap則是最初始的前端技術做手機App的開發框架,當時社區內部也有不少前端在討論這個技術,以至於后來催生了國內前端移動化的一個趨勢。
例如Dcloud、APICloud、AppCan這些國內的前端做移動App的框架,其中Dcloud和APICloud曾經還因為源碼事件撕逼過一段時間,這一切都是因為phonegap這樣技術催生了國內開發者的視野。
后來phonegap優化成了一部分,發展成了Cordova這門技術。
在RN還未出現的時刻,Cordova可謂是如日中天,當時我曾經也做過幾個Cordova項目,在商業趨於移動化的年代,Cordova技術每個移動前端必會的技術。
而當時比較火熱的技術angularjs,當時還是1.0臟檢查階段,於是結合Cordova、angularjs發展出來的移動端開發UI框架IONIC應運而生。
IONIC在angularjs在國內前端市場占據百分之九十以上市場的時候曾經也算火熱一時,國內涌現了許多利用該技術制作的App。
但,angularjs后來被新興的單向數據流技術React搶占了大量的市場,以至於市場份額落后到了百分之十左右程度,導致IONIC也受到了發展局限,性能問題頻出。
更別說后來React Native的出現,利用JS寫原生組件這個概念當時甚囂塵上,我當時的公司也有將App專項RN開發的想法。
雖然后來Angular更新換代,有了2.0、4和Angular5,性能得到了很大的提升,避免了過量臟檢查機制,但好似錯過了黃金年代,市場份額則是不慍不火。
IONIC從2018年開始集成React技術,並且在2019年可以投入使用,中間一直是Angular和TS在支撐着平台前進。
但說到底,IONIC只是開發瀏覽器應用,而不是真正的原生應用,和React Native有很大的區別的。
不過,最近隨着大家手機性能的提升,其實原生應用和瀏覽器應用,在性能上幾乎是看不出差異,但如今國內前端圈很多人只知道React Native、Flutter而不知IONIC,實在是有些尷尬。
最近我也重新撿起這門技術,看看這個React應用到底在IONIC上做了哪些事情。
React + TypeScript
IONIC的React引入,同樣和Angular一樣,都是利用TypeScript做類型檢查。並且直接引入的React的高級版本,現如今支持FC和Hooks特性。
下面來一段生成的應用中的代碼:
const App: React.FunctionComponent = () => (
<IonApp>
<IonReactRouter>
<IonPage id="main">
<IonTabs>
<IonRouterOutlet>
<Route path="/:tab(books)" component={Books}/>
<Route path="/:tab(home)" component={Home} exact={true} />
<Route path="/:tab(books)/details" component={Details} />
<Route path="/:tab(cate)" component={Categaray} />
<Route exact path="/" render={() => <Redirect to="/home" />} />
</IonRouterOutlet>
<IonTabBar slot="bottom">
<IonTabButton tab="schedule" href="/books">
<IonIcon icon={book} />
<IonLabel>書架</IonLabel>
</IonTabButton>
<IonTabButton tab="speakers" href="/home">
<IonIcon icon={apps} />
<IonLabel>書城</IonLabel>
</IonTabButton>
<IonTabButton tab="map" href="/cate">
<IonIcon icon={send} />
<IonLabel>分類</IonLabel>
</IonTabButton>
</IonTabBar>
</IonTabs>
</IonPage>
</IonReactRouter>
</IonApp>
);
組件化
IONIC是個UI框架,已經把組建平台分裝成了React組件,可以直接引用就可。
import { RouteComponentProps } from 'react-router';
import { IonItem, IonLabel, IonList, IonThumbnail, IonContent } from '@ionic/react';
不過,我嘗試寫了一個組件,引入發生報錯信息:
Type '{}' is missing the following properties from type 'Readonly<RouteComponentProps<{}, StaticContext, any>>': history, location, matchts(2739)
可見,在IONIC下寫一些組件,似乎是失去了自由,感覺略微有些尷尬,這個組件化似乎是不徹底?
不過,在項目中可以直接用div去寫當前組件,但這樣似乎是不能共用?
稍等,這是TypeScript的校驗,於是我們需要做一些修改:
import { Header } from '../../components'
interface props {
Header?: PureComponent
}
class Home extends React.PureComponent<props, {}> {}
Header組件經過改造終於可以用了,那么,我們就可以通過寫Web的方式,來開發移動端的應用了。
工程化
1、Icon
對一個對應用有想法的人,ionicons滿足不了項目需求,於是,這個時候可以選擇引入iconfont或者font asome
因為我並不是美工,也沒人上傳到iconfont一些圖標,於是我選擇引入fontasome:
直接在public/index.html以CDN的方式引入:
<link href="http://netdna.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet">
項目中直接用:
<i className="fa fa-home fa-fw"></i>
<i className="fa fa-book fa-fw"></i>
2、Request
利用fetch添加通用請求方式(其實也可以用別的):
import _ from 'lodash'
interface HttpProps {
url: string,
method: string,
body: object
}
export default function httpRequest(httpProps: HttpProps) {
const init = {
method: httpProps.method,
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
'Accept-language': 'zh-CN',
},
body: ''
}
if (httpProps.method !== 'GET') {
init.body = JSON.stringify(httpProps.body);
}
return fetch(httpProps.url, init).then(checkStatus, (err) => console.warn('===>request checkStatus error', err)).then(
(val) => {
const result = val.json();
console.log(
`%c fetch end: ${httpProps.url}`,
'color: green;font-size: 14px;font-weight:bold;',
result,
);
return result;
},
(err) => {
console.warn('===>parse json error', err);
},
).catch((err) => {
console.error('###ERROR###', err);
});
}
function checkStatus(response: any) {
const status = _.get(response, 'status');
if (status >= 200 && status < 300) {
return response;
}
throw new Error('status wrong');
}
請求文件可以直接用這個寫好的封裝:
// import _ from 'lodash';
import { config, httpRequest } from '../utils';
interface ReturnProps{
result: object,
}
interface RequestBody {
url: string
}
export default class HttpService<ReturnProps, RequestBody> {
getHomePages = async (requestBody: RequestBody) => {
const url = config.baseUrl;
const result = await httpRequest({url, method: 'GET', body: {}})
console.log('result==============>', result)
return result
}
}
這個時候,是不是想要引入Redux?
3、Redux
在引入Redux主要是通過saga這種方式,這時候基本上要添加的是sagas、reducer、actions。
首先添加Actions:
export const FAIL_GETHOME = 'FAIL_GETHOME'
export const SUCCESS_GETHOME = 'SUCCESS_GETHOME'
export const GET_HOMEDATA = 'GET_HOMEDATA'
添加Reducers:
// import _ from 'lodash';
import { FAIL_GETHOME, SUCCESS_GETHOME, GET_HOMEDATA } from '../actions/home';
const initState = {
loading: false
}
export default function homeReducer(state = initState, action: any) {
if (action.type === GET_HOMEDATA) {
return {
...state,
loading: true,
};
} else if (action.type === SUCCESS_GETHOME) {
return {
...state,
loading: false,
};
} else if (action.type === FAIL_GETHOME) {
return {
...state,
loading: false,
};
}
return state;
}
添加sagas處理請求:
import _ from 'lodash';
import { call, put, takeEvery } from 'redux-saga/effects';
import { FAIL_GETHOME, SUCCESS_GETHOME, GET_HOMEDATA } from '../actions/home';
import HttpService from '../services/http-service';
function* getHomeData(action: any) {
const key = _.get(action, 'key');
const httpSerice = new HttpService()
try {
const data = yield call(httpSerice.getHomePages, action.payload);
if (!data) {
yield put({ type: FAIL_GETHOME, status: 2, key });
} else {
yield put({ type: SUCCESS_GETHOME, status: 0, payload: data, key });
}
} catch (e) {
yield put({ type: FAIL_GETHOME, status: 1, key });
}
}
export function* watchGetHomeData() {
yield takeEvery(GET_HOMEDATA, getHomeData)
}
到這里一個基本的Redux流程添加完畢。接下來可以在項目中觸發Actions,來進行數據請求了。
IONIC和RN
最后談談IONIC這門技術和React Native的區別。
兩者都是基於某種技術的一種UI開發App方式,IONIC的組件相對比較完善,RN的組件則是比較簡單。
開發方式來說,IONIC則是瀏覽器開發方式,相當於是開發的是一個webapp,但是RN開發出來的是原生應用。這是兩者主要的技術區別。
上手來說,毫無疑問,IONIC的開發上手起來更快,其實是IONIC的開發就是普通的web+UI框架開發,而RN則還有些前置理解成本。
總的來說,現如今性能方面漸漸被日漸性能提升的手機抹平,其實在這個時候,回過頭再看IONIC,也是一種不錯的選擇,不是嗎?