zoukankan      html  css  js  c++  java
  • 谈谈IONIC版本中加入的React开发方式

    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,也是一种不错的选择,不是吗?

    我的博客

  • 相关阅读:
    Spring注释事务失效及解决办法
    在使用springMVC时,我使用了@Service这样的注解,发现使用注解@Transactional声明的事务不起作用
    如何在Oracle中复制表结构和表数据
    Tomcat Deployment failure ,locked one or more files
    java中对List中对象排序实现
    HDU 5002 Tree LCT 区间更新
    2014-2015 ACM-ICPC, Asia Xian Regional Contest G The Problem to Slow Down You 回文树
    Codeforces Round #323 (Div. 1) B. Once Again... 暴力
    Codeforces Round #323 (Div. 2) C. GCD Table 暴力
    hdu 5497 Inversion 树状数组 逆序对,单点修改
  • 原文地址:https://www.cnblogs.com/qixingduanyan/p/12912194.html
Copyright © 2011-2022 走看看