(轉)移動端開發通用坑

一、click300ms延遲?

講道理,如今開發移動端基本是不會有這麼一個問題的。但做爲移動端之前的經典坑,我這裏也拿出來講上一說吧。
移動設備上的web網頁是有300ms延遲的,玩玩會形成按鈕點擊延遲甚至是點擊失效。這是因爲區分單擊事件和雙擊屏幕縮放的歷史緣由形成的。但在2014年的Chrome 32版本已經把這個延遲去掉了,so you know。但若是你仍是出現了300ms的延遲問題,也是有路子搞定的。css

解決方案以下:html

1.fastclick能夠解決在手機上點擊事件的300ms延遲前端

2.zepto的touch模塊,tap事件也是爲了解決在click的延遲問題vue

3.觸摸事件的響應順序爲 touchstart --> touchmove --> touchend --> click,也能夠經過綁定ontouchstart事件,加快對事件的響應,解決300ms延遲問題jquery

4.若移動設備兼容性正常的話(IE/Firefox/Safari(IOS 9.3)及以上),只需加上一個meta標籤android

<meta name="viewport" content="width=device-width"> 

即把viewport設置成設備的實際像素,那麼就不會有這300ms的延遲。webpack

二、移動端樣式兼容處理

當今的手機端,各式各樣的手機,屏幕分辨率也是各有不一樣,爲了讓頁面能夠能夠兼容各大手機,解決方案以下ios

1.設置meta標籤viewport屬性,使其無視設備的真實分辨率,直接經過dpi,在物理尺寸和瀏覽器之間重設分辨率,從而達到能有統一的分辨率的效果。而且禁止掉用戶縮放git

<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no" /> 

2.使用rem進行屏幕適配,設置好root元素的font-size大小,而後在開發的時候,全部與像素有關的佈局統一換成rem單位。針對不一樣的手機,使用媒體查詢對root元素font-size進行調整github

三、阻止旋轉屏幕時自動調整字體大小

移動端開發時,屏幕有豎屏和橫屏模式,當屏幕進行旋轉時,字體大小則有可能會發生變化,從而影響頁面佈局的總體樣式,爲避免此類狀況發生,只需設置以下樣式便可

  1.  
    * {
  2.  
    -webkit-text-size-adjust: none;
  3.  
    }

四、修改移動端難看的點擊的高亮效果,iOS和安卓下都有效

  1.  
    * {
  2.  
    -webkit-tap-highlight-color: rgba( 0,0,0,0);
  3.  
    }

不過這個方法在如今的安卓瀏覽器下,只能去掉那個橙色的背景色,點擊產生的高亮邊框仍是沒有去掉,有待解決!

一個CSS3的屬性,加上後,所關聯的元素的事件監聽都會失效,等於讓元素變得「看得見,點不着」。IE到11纔開始支持,其餘瀏覽器的當前版本基本都支持。詳細介紹見這

pointer-events: none;

五、iOS下取消input在輸入的時候英文首字母的默認大寫

<input type="text" autocapitalize="none"> 

六、禁止 iOS 識別長串數字爲電話

<meta name="format-detection" content="telephone=no" /> 

七、禁止 iOS 彈出各類操做窗口

-webkit-touch-callout: none;

八、禁止ios和android用戶選中文字

-webkit-user-select: none; 

九、calc的兼容處理nainaitea.com

CSS3中的calc變量在iOS6瀏覽器中必須加-webkit-前綴,目前的FF瀏覽器已經無需-moz-前綴。 Android瀏覽器目前仍然不支持calc,因此要在以前增長一個保守尺寸:

  1.  
    div {
  2.  
    width: 95%;
  3.  
    width: -webkit-calc( 100% - 50px);
  4.  
    width: calc( 100% - 50px);
  5.  
    }

十、fixed定位缺陷

  1.  
    iOS下 fixed元素容易定位出錯,軟鍵盤彈出時,影響fixed元素定位,android下fixed表現要比iOS更好,軟鍵盤彈出時,不會影響fixed元素定位 。iOS4下不支持position:fixed
  2.  
     
  3.  
    解決方案: 可用iScroll插件解決這個問題

十一、一些狀況下對非可點擊元素如(label,span)監聽click事件,ios下不會觸發

針對此種狀況只須要對不觸發click事件的那些元素添加一行css代碼便可

cursor: pointer;

十二、消除transition閃屏問題

  1.  
    /*設置內嵌的元素在 3D 空間如何呈現:保留 3D*/
  2.  
    -webkit-transform-style: preserve -3d;
  3.  
    /*(設置進行轉換的元素的背面在面對用戶時是否可見:隱藏)*/
  4.  
    -webkit-backface-visibility: hidden;

1三、CSS動畫頁面閃白,動畫卡頓

解決方法:

1.儘量地使用合成屬性transform和opacity來設計CSS3動畫,不使用position的left和top來定位
2.開啓硬件加速

  1.  
    -webkit-transform: translate3d( 0, 0, 0);
  2.  
    -moz-transform: translate3d( 0, 0, 0);
  3.  
    -ms-transform: translate3d( 0, 0, 0);
  4.  
    transform: translate3d( 0, 0, 0);

1四、iOS系統中文輸入法輸入英文時,字母之間可能會出現一個六分之一的空格

解決方法:經過正則去除

this.value = this.value.replace(/\u2006/g, ‘‘); 

1五、input的placeholder會出現文本位置偏上的狀況

input 的placeholder會出現文本位置偏上的狀況:PC端設置line-height等於height可以對齊,而移動端仍然是偏上,解決方案時是設置css

line-height:normal;

1六、浮動子元素撐開父元素盒子高度

解決方法以下:

  1. 父元素設置爲 overflow: hidden;
  2. 父元素設置爲 display: inline-block; 等

這裏兩種方法都是經過設置css屬性將浮動元素的父元素變成間接變成BFC元素,而後使得子元素高度能夠撐開父元素。這裏須要注意的時,最好使用方法1, 由於inline-block元素自己會自帶一些寬高度撐開其自己。

1七、往返緩存問題

點擊瀏覽器的回退,有時候不會自動執行js,特別是在mobilesafari中。這與往返緩存(bfcache)有關係。 解決方法 :

window.onunload = function () {};

1八、overflow-x: auto在iOS有兼容問題

解決方法:

-webkit-overflow-scrolling: touch;

  

2、vue移動開發特有坑以及小技巧分享

一、iOS原始輸入法問題

iOS原始輸入法,中文輸入時,沒法觸發keyup事件,且keyup.enter事件不管中英文,都沒法觸發

解決方法:

  1. 改用input事件進行監聽
  2. 將keyup監聽替換成值的watch
  3. 讓使用者安裝三方輸入法,好比搜狗輸入法(不太現實)

二、input元素失焦問題

業務場景重現: 項目中須要寫一個搜索組件,相關代碼以下

  1.  
    <template>
  2.  
    <div class="y-search" :style="styles" :clear="clear">
  3.  
    <form action= "#" onsubmit="return false;">
  4.  
    <input type= "search"
  5.  
    class="y-search-input"
  6.  
    ref="search"
  7.  
    v-model=‘model‘
  8.  
    :placeholder= "placeholder"
  9.  
    @input= "searchInputFn"
  10.  
    @keyup.enter= "searchEnterFn"
  11.  
    @foucs= "searchFocusFn"
  12.  
    @blur= "searchBlurFn"
  13.  
    />
  14.  
    <y-icons class="search-icon" name="search" size="14"></y-icons>
  15.  
    </form>
  16.  
    <div v- if="showClose" @click="closeFn">
  17.  
    <y-icons class="close-icon" name=‘close‘ size=‘12‘></y-icons>
  18.  
    </div>
  19.  
    </div>
  20.  
    </template>

其中我須要在enter的時候進行對應的搜索操做並實現失焦,解決方法其實很簡單,在enter時進行DOM操做便可

  1.  
    searchEnterFn (e) {
  2.  
    document.getElementsByClassName(‘y-search-input‘)[ 0].blur()
  3.  
    // dosomething yourself
  4.  
    }

  

對了,這裏還有一個坑,就是在移動端使用input類型爲search的時候,必須使用form標籤包裹起來,這樣在移動端呼出鍵盤的enter纔會是搜索按鈕,不然只是默認的enter按鈕。

三、vue組件開發

這個點不能算坑,只能算是小技巧分享吧。

業務場景重現:不少時候,在開發項目的時候是須要抽離公共組件和業務組件的。而有些公共組件在全局註冊的同時可能還須要拓展成vue的實例方法,經過把它們添加到 Vue.prototype 上實現,方便直接使用js全局調用。拿一個Message組件作例子吧,代碼比較簡單,就直接上代碼了。

1.首先開發好Message.vue文件。

  1.  
    <template>
  2.  
    <div class=‘y-mask-white-dialog‘ v-show=‘show‘>
  3.  
    <div class=‘y-message animated zoomIn‘ >
  4.  
    <span v-html= "msg"></span>
  5.  
    </div>
  6.  
    </div>
  7.  
    </template>
  8.  
     
  9.  
    <script>
  10.  
    export default {
  11.  
    name: ‘yMessage‘,
  12.  
    props: {
  13.  
    msg: String,
  14.  
    timeout: Number,
  15.  
    callback: Function,
  16.  
    icon: String,
  17.  
    },
  18.  
    data() {
  19.  
    return {
  20.  
    show: true,
  21.  
    };
  22.  
    }
  23.  
    };
  24.  
    </script>
  25.  
     
  26.  
    <style lang= "stylus" scoped>
  27.  
    .y-mask-white-dialog {
  28.  
    outline: 0px; margin: 0px; padding: 0px; color: rgb(152, 104, 1); overflow-wrap: break-word;">0, 0, 0, .4);
  29.  
    position: fixed;
  30.  
    z-index: 999;
  31.  
    bottom: 0;
  32.  
    right: 0;
  33.  
    left: 0;
  34.  
    top: 0;
  35.  
    display: -webkit-box;
  36.  
    display: -webkit-flex;
  37.  
    display: -ms-flexbox;
  38.  
    display: flex;
  39.  
    -webkit-box-pack: center;
  40.  
    -webkit-justify-content: center;
  41.  
    -ms-flex-pack: center;
  42.  
    justify-content: center;
  43.  
    -webkit-box-align: center;
  44.  
    -webkit-align-items: center;
  45.  
    -ms-flex-align: center;
  46.  
    align-items: center;
  47.  
    }
  48.  
    .y-message {
  49.  
    min-width: 2.9rem;
  50.  
    max-width: 5.5rem;
  51.  
    width: 100%;
  52.  
    padding: 0.32rem;
  53.  
    font-size: 14px;
  54.  
    text-align: center;
  55.  
    border-radius: 4px;
  56.  
    background :rgba( 0,0,0,0.8);
  57.  
    color: #fff;
  58.  
    animation: zoomIn .15s ease forwards;
  59.  
    }
  60.  
    </style>

2.構建Message的Constructor

  1.  
    import Vue from ‘vue‘;
  2.  
     
  3.  
    const MsgConstructor = Vue.extend(require(‘./Message.vue‘));
  4.  
     
  5.  
    const instance = new MsgConstructor({
  6.  
    // el: document.createElement(‘div‘),
  7.  
    }).$mount(document.createElement(‘div‘));
  8.  
     
  9.  
    MsgConstructor.prototype.closeMsg = function () {
  10.  
    const el = instance.$el;
  11.  
    el.parentNode && el.parentNode.removeChild(el);
  12.  
    typeof this.callback === ‘function‘ && this.callback();
  13.  
    };
  14.  
     
  15.  
    const Message = (options = {}) => {
  16.  
    instance.msg = options.msg;
  17.  
    instance.timeout = options.timeout || 2000;
  18.  
    instance.icon = options.icon;
  19.  
    instance.callback = options.callback;
  20.  
    document.body.appendChild(instance.$el);
  21.  
     
  22.  
    const timer = setTimeout(() => {
  23.  
    clearTimeout(timer);
  24.  
    instance.closeMsg();
  25.  
    }, instance.timeout + 100);
  26.  
    };
  27.  
     
  28.  
    export default Message;

3.在main.js裏面進行組件註冊

  1.  
    import Message from ‘./components/Message‘;
  2.  
     
  3.  
    Vue.component(Message.name, Message)
  4.  
    Vue.prototype.$message = Message

而後你就能夠盡情使用Message組件了.

  1.  
    this.$message({
  2.  
    msg: ‘test message‘
  3.  
    // ...
  4.  
    })

四、巧用flex佈局讓圖片等比縮放

這也是一個小技巧!項目中須要開發swiper輪播圖,那麼你懂的,圖片確定是須要保證等比縮放展現。

  1.  
    <div class="parent">
  2.  
    <img :src= "imgSrc" >
  3.  
    </div>
  4.  
     
  5.  
    <style lang= "stylus" scoped>
  6.  
    .parent {
  7.  
    width: 100px;
  8.  
    height: 100px;
  9.  
    display: flex;
  10.  
    align-items: center;
  11.  
     
  12.  
    img {
  13.  
    width : 100%;
  14.  
    height: auto;
  15.  
    }
  16.  
    }
  17.  
    </style>

是否是賊簡單,是的,賊簡單。這個樣式同時適應手機全屏預覽豎屏的狀況,當手機橫屏的時候,加一個媒體查詢便可搞定

  1.  
    @media (orientation: landscape) {
  2.  
    img {
  3.  
    width auto
  4.  
    height 100%
  5.  
    margin auto
  6.  
    }
  7.  
    }

  

五、枚舉值過濾處理

業務重現:考慮到項目後期會作國際化,前端須要對項目中幾乎全部的枚舉值進行過濾處理,從而進行展現

接下來就直接講講這塊吧。既然要過濾,那麼首選確定是vue提供的filter指令。這裏我舉一個支付方式的枚舉值處理的例子。首先配置代碼以下

  1.  
    // 配置文件
  2.  
    export default {
  3.  
    env: (process.env.NODE_ENV === ‘development‘ ? require(‘./env/dev‘) : require(‘./env/pro‘)),
  4.  
    headShow: false,
  5.  
    lng: ‘zh‘,
  6.  
    };

 枚舉代碼以下

  1.  
    // 獲取語言環境
  2.  
    import config from ‘../config/index‘;
  3.  
     
  4.  
    const {lng} = config;
  5.  
    // 帳戶類型
  6.  
    const type = {
  7.  
    zh: {
  8.  
    1: ‘銀行‘,
  9.  
    2: ‘支付寶‘,
  10.  
    3: ‘微信支付‘,
  11.  
    },
  12.  
    en: {
  13.  
    1: ‘bank_type‘,
  14.  
    2: ‘alipay_type‘,
  15.  
    3: ‘wxpay_type‘,
  16.  
    }
  17.  
    }
  18.  
    export default type[lng];

枚舉註冊代碼分別以下

  1.  
    import accountType from ‘./accountType‘; // 帳戶類型
  2.  
     
  3.  
    const factory = {
  4.  
    accountType( value) {
  5.  
    if (value === -1) {
  6.  
    return ‘請選擇帳戶類型‘;
  7.  
    }
  8.  
    return accountType[value] ? accountType[value] : ‘請選擇帳戶類型‘;
  9.  
    }
  10.  
    }
  11.  
    const filter = [
  12.  
    {
  13.  
    name: ‘formatEnum‘, // 過濾類型
  14.  
    filter: function( value, type, status) {
  15.  
    return factory[type](value, status);
  16.  
    }
  17.  
    }
  18.  
    ];
  19.  
    export default {
  20.  
    filter
  21.  
    };
  22.  
    // filter
  23.  
    import baseFilter from ‘./filter/index‘;
  24.  
     
  25.  
    const filters = [
  26.  
    ...baseFilter.filter
  27.  
    ];
  28.  
    filters.map(f => {
  29.  
    Vue.filter(f.name, f.filter);
  30.  
    return ‘‘;
  31.  
    });

接下來就能夠輕鬆使用啦

  1.  
    <li>
  2.  
    <label支付類型</label>
  3.  
    <span>
  4.  
    {{info.account_type | formatEnum(‘accountType‘)}}
  5.  
    </span>
  6.  
    </li>

六、時間過濾處理

這點仍是屬於過濾處理的一個part,可是手機端有個兼容問題,若是是時間戳轉的話,那麼能夠轉化成任意咱們想要的形式,可是String類型的時間轉化的話,他只能兼容 "yyyy/MM/dd" 形式的時間值,由於咱們DateTime組件默認的形式是"yyyy-MM-dd",那麼只須要在DateTime組件正則替換一下便可,代碼以下
currentValue = _this.currentValue = _this.value ? _this.value.replace(/-/g, ‘/‘) : ‘‘; 

時間過濾代碼以下

  1.  
    const filter = [
  2.  
    {
  3.  
    name: ‘formatEnum‘, // 過濾類型
  4.  
    filter: function( value, type, status) {
  5.  
    return factory[type](value, status);
  6.  
    }
  7.  
    },
  8.  
    {
  9.  
    name: ‘formatDate‘, // 日期
  10.  
    filter: function( value, format = ‘yyyy-MM-dd‘) {
  11.  
    if (!value || value === ‘‘) return ‘‘;
  12.  
    let v = value;
  13.  
    if (!isNaN(value)) {
  14.  
    v = + value * 1000;
  15.  
    }
  16.  
    const newDate = new Date(v);
  17.  
    return newDate.Format(format);
  18.  
    },
  19.  
    }
  20.  
    ];

  

七、路由權限斷定

業務重現:因爲不一樣的用戶,可能擁有不一樣權限,而目前咱們的項目是基於微信公衆號進行開發的,頁面權限這邊也是交給了咱們前端處理。既然要前端配置權限,那麼咱們能想到的比較好的方式就是經過配置路由文件,完成權限斷定。下面我會列舉一小部分代碼(以咱們的工單列表)進行演示,路由配置代碼以下

  1.  
    const getWorkOrder = pageName => resolve => require([‘../pages/WorkOrder‘], pages => resolve(pages[pageName]))
  2.  
     
  3.  
    let routers = [];
  4.  
    routers = [
  5.  
    {
  6.  
    path: ‘/workorder‘,
  7.  
    name: ‘workorder‘,
  8.  
    component: room,
  9.  
    children: [
  10.  
    {
  11.  
    path: ‘list‘, // 管家端工單列表
  12.  
    name: ‘list‘,
  13.  
    rule: 3,
  14.  
    component: getWorkOrder(‘WorkOrderList‘) //WorkOrder,
  15.  
    },
  16.  
    {
  17.  
    path: ‘managerList‘, // 店長端工單列表
  18.  
    name: ‘managerList‘,
  19.  
    rule: 6,
  20.  
    component: getWorkOrder(‘ManagerWorkOrder‘) // WorkOrder,
  21.  
    },
  22.  
    ]
  23.  
    }
  24.  
    ]

而後進行路由統一過濾處理

  1.  
    import Vue from ‘vue‘;
  2.  
    import Store from ‘store‘;
  3.  
    import Router from ‘vue-router‘;
  4.  
     
  5.  
    import routers from ‘./router.config‘;
  6.  
    Vue.use(Router);
  7.  
     
  8.  
    // 遍歷路由名稱以及權限
  9.  
    let arr = {};
  10.  
    const routeName = function (router) {
  11.  
    if (!router) return false;
  12.  
    router.forEach((v) => {
  13.  
    arr[v.name] = v.rule;
  14.  
    routeName(v.children);
  15.  
    })
  16.  
    }
  17.  
    routeName(routers);
  18.  
     
  19.  
    const RouterModel = new Router({
  20.  
    mode: ‘history‘,
  21.  
    routes: routers,
  22.  
    });
  23.  
     
  24.  
    // 路由鉤子,進入路由以前判斷
  25.  
    RouterModel.beforeEach((to, from, next) => {
  26.  
    // 處理query 參數,傳入到 jumpUrl,便於登陸後跳轉到對應頁面
  27.  
    let qu = Object.entries(to.query);
  28.  
    if (qu.length > 0) {
  29.  
    qu = qu.map((item, index) => {
  30.  
    return item.join(‘=‘);
  31.  
    })
  32.  
    }
  33.  
    if (arr[to.name]) {
  34.  
    // 若是有權限須要
  35.  
    const userInfo = Store.get(‘yu_info‘);
  36.  
    const cookie = Vue.prototype.$util.getCookie(‘X-Auth-Token‘);
  37.  
    const userId = Vue.prototype.$util.getCookie(‘userid‘);
  38.  
    if (userInfo && cookie && +userId > 0) {
  39.  
    next();
  40.  
    } else {
  41.  
    // 未登陸,跳轉登陸
  42.  
    let param = `jumpUrl=${to.path}`;
  43.  
    if (qu.length > 0) {
  44.  
    param += `&${qu. join("&")}`;
  45.  
    }
  46.  
    if (arr[to.name] && !to.query.rule) {
  47.  
    param += `&rule=${arr[to.name]}`;
  48.  
    }
  49.  
    window.location.href = `/login?${param}`;
  50.  
    }
  51.  
    } else {
  52.  
    // 若是不須要權限放行
  53.  
    next();
  54.  
    }
  55.  
    })
  56.  
     
  57.  
    export default RouterModel;

而後在登錄界面定位到微信受權

  1.  
     
  2.  
    getCode() {
  3.  
    // 定位到微信受權,如果不須要受權能夠在此到處理
  4.  
    let query = this.$route.query;
  5.  
    let param = `jumpUrl=${query.jumpUrl || ‘/home‘}`;
  6.  
    let path = window.location.origin;
  7.  
    // 登陸角色處理
  8.  
    let cfg = api[query.rule ? query.rule : 1];
  9.  
    if (query.rule) {
  10.  
    param += `&rule=${query.rule}`;
  11.  
    }
  12.  
     
  13.  
    let redirect_url = encodeURIComponent(`${path}/login?${param}`);
  14.  
    let url = `https://open.weixin.qq.com/connect/oauth2/authorize?appid=${cfg.tempApp}&redirect_uri=${redirect_url}&response_type=code&scope=snsapi_userinfo&state=1#wechat_redirect`;
  15.  
    if (query.rule === 3) {
  16.  
    url += ‘&agentid= 1000004‘;
  17.  
    }
  18.  
    location.replace = url;
  19.  
    }
  20.  
     

若是不是微信端,訪問到到rule規則的界面時,則會以下

技術分享

而當微信受權經過的時候,rule權限不足的狀況則會以下

技術分享

八、使用vue-cli proxyTable進行反向代理,解決跨域問題

開發項目,在先後端聯調的時候確定是會趕上跨域的問題的。很簡單,作個反向代理唄,對於想了解正向代理和反向代理的,請點擊這裏

vue-cli腳手架搭建的工程中,在config/index.js文件中能夠利用預留的proxyTable一項,設置地址映射表,以下

  1.  
    proxyTable: {
  2.  
    ‘/api‘: {
  3.  
    target: ‘http: //www.example.com‘, // your target host
  4.  
    changeOrigin: true, // needed for virtual hosted sites
  5.  
    pathRewrite: {
  6.  
    ‘^/api‘: ‘‘ // rewrite path
  7.  
    }
  8.  
    }
  9.  
    }

而後使用http-proxy-middleware插件對api請求地址進行代理

  1.  
    // proxy api requests
  2.  
    Object.keys(proxyTable).forEach(function (context) {
  3.  
    var options = proxyTable[context]
  4.  
    if (typeof options === ‘string‘) {
  5.  
    options = { target: options }
  6.  
    }
  7.  
    app.use(proxyMiddleware(options.filter || context, options))
  8.  
    })

http-proxy-middleware地址

 

3、移動端開發性能優化

技術分享

一、首屏渲染優化

決定用戶體驗最重要的一個點之一,這個點的重要性,相信不用我說了。下面直接談實戰。

  • 減小資源請求次數
  • 加載時使用過渡樣式,防止用戶網絡太差影響對首頁的體驗
  • 圖片使用懶加載,這一part,咱們目前項目中使用的vue的三方插件vue-lazyload,大體使用方法以下
  1.  
    // 全局註冊 import VueLazyload from ‘vue-lazyload‘;
  2.  
     
  3.  
    Vue.use(VueLazyload, {
  4.  
    error: require(‘./assets/close.svg‘),
  5.  
    loading: require(‘./assets/loading.svg‘),
  6.  
    attempt: 1,
  7.  
    });
  8.  
     
  9.  
    // 使用
  10.  
    <img v-lazy= "room.img" :alt="room.community_name" width="100%">
  • HTML使用Viewport,Viewport能夠加速頁面的渲染。
    <meta name=」viewport」 content=」width=device-width, initial-scale=1″>

除此以外,還有不少點可作優化,進而提高首屏加載速度。

二、雪碧圖

這個老生常談了,爲了減小圖片請求次數,加快頁面加載,固然會考慮使用雪碧圖。儘可能使用::before或::after僞類,Sprites中的圖片排版能夠更緊 ,圖片體積更小, HTML更簡潔。

  1.  
    <style lang= "stylus" scoped>
  2.  
    .chose-house {
  3.  
    height: 86px;
  4.  
    width: 64px;
  5.  
    margin 0 auto
  6.  
    position relative
  7.  
    &::before {
  8.  
    content: ‘\ 20‘;
  9.  
    height: 100%;
  10.  
    width: 100%;
  11.  
    position: absolute;
  12.  
    left: 0;
  13.  
    top: 0;
  14.  
    background: url(‘../../assets/sprite-min.png‘) 0px 0px no-repeat;
  15.  
    }
  16.  
    }
  17.  
    </style>

三、路由懶加載

關於路由懶加載這一部分,尤大在vue-router文檔中也有所說起,連接點擊這裏

其實在vue項目中使用路由懶加載很是簡單,咱們要作的就是把路由對應的組件定義成異步組件,代碼以下

  1.  
    //在router/index.js中引入組件時可以使用以下異步方式引入
  2.  
    const Foo = resolve => {
  3.  
    // require.ensure 是 Webpack 的特殊語法,用來設置 code-split point
  4.  
    // (代碼分塊)
  5.  
    require.ensure([‘./Foo.vue‘], () => {
  6.  
    resolve(require(‘./Foo.vue‘))
  7.  
    })
  8.  
    }
  9.  
    // or
  10.  
    const Foo = resolve => require([‘./Foo.vue‘], resolve)

再將組件按組分塊,如

const Foo = r => require.ensure([], () => r(require(‘./Foo.vue‘)), ‘group-foo‘) 

實際項目中的代碼則如同我在章節《路由權限斷定》說起到的同樣

  1.  
    const getWorkOrder = pageName => resolve => require([‘../pages/WorkOrder‘], pages => resolve(pages[pageName]))
  2.  
     
  3.  
    let routers = [];
  4.  
    routers = [
  5.  
    {
  6.  
    path: ‘/workorder‘,
  7.  
    name: ‘workorder‘,
  8.  
    component: room,
  9.  
    children: [
  10.  
    {
  11.  
    path: ‘list‘, // 管家端工單列表
  12.  
    name: ‘list‘,
  13.  
    rule: 3,
  14.  
    component: getWorkOrder(‘WorkOrderList‘) //WorkOrder,
  15.  
    },
  16.  
    {
  17.  
    path: ‘managerList‘, // 店長端工單列表
  18.  
    name: ‘managerList‘,
  19.  
    rule: 6,
  20.  
    component: getWorkOrder(‘ManagerWorkOrder‘) // WorkOrder,
  21.  
    },
  22.  
    ]
  23.  
    }
  24.  
    ]

如上將組件經過傳遞pageName參數分別打包到了各個chunk中,這樣每一個組件加載時都只會加載本身對應的代碼,從而加快渲染速度!

四、全局組件按需註冊

當時咱們爲了優化首屏渲染速度,也是考慮到這一點,項目的src/main.js文件主要負責註冊全局組件,插件,路由,以及實例化Vue等。在webpack的配置裏面也是當成entry入口進行了配置,若是我在main.js裏面講每一個組件都進行import的話,那麼它將會所有一塊兒註冊打包,頁面加載也會將每一個組件文件都加載下來,這樣對渲染速度仍是有必定影響的。

解決方法就是:按需註冊,這樣在打包的時候,會按需加載首頁(其餘界面也一樣適用)使用到的全局組件。基本步驟以下:

將須要註冊的組件寫進components/base.js文件中,而後exports出來

  1.  
    exports.Foo = require(‘./Foo.vue‘);
  2.  
    exports.Bar = require(‘./Bar.vue‘);
  3.  
    exports.Baz = require(‘./Baz.vue‘);

在main.js中進行註冊

  1.  
    const components = [
  2.  
    require(‘./components/ base‘).Foo,
  3.  
    require(‘./components/ base‘).Bar,
  4.  
    require(‘./components/ base‘).Baz,
  5.  
    ];
  6.  
     
  7.  
    components.map(component => {
  8.  
    Vue.component(component.name, component);
  9.  
    });

  



 

 

hybird應用開發的坑:

1:ios狀態欄與頁面內容重疊(webview中),若是是在微信端的網頁,能夠忽略這個坑。

解決方法:判斷設備類型,若是是ios則加入獨有的樣式:通常狀態欄的高度是20px

  1.  
    var u = navigator.userAgent, app = navigator.appVersion;
  2.  
    var isiOS = !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/); //ios終端
  3.  
    if(isiOS){
  4.  
    $( "body").addClass("uh_ios7");
  5.  
    }

樣式文件下加這段:

  1.  
    .uh_ios7 .uh,.uh_ios7{
  2.  
    padding: 20px 0 0;
  3.  
    }

 

3:當頁面輸入框獲取焦點的時候,ios頁面滾動致使頭部與狀態欄重疊:

首先咱們下載插件: 傳送門

cordova plugin add ionic-plugin-keyboard. 

 而後在app.js中加入代碼:

  1.  
    $ionicPlatform.ready(function () {
  2.  
    if (window.cordova && window.cordova.plugins.Keyboard) {
  3.  
    window.cordova.plugins.Keyboard.hideKeyboardAccessoryBar( false);
  4.  
    if (window.ionic.Platform.isIOS()) {
  5.  
    window.cordova.plugins.Keyboard.disableScroll( true);
  6.  
    }
  7.  
    }
  8.  
    });

注意:在ios上$ionicPlatform.ready可能進不去————解決辦法就是:

將cordova.js放在頁面最底部引入!!!!fuck!!

 

4:ios上如何讓絕對定位在頁面底部的輸入框,隨鍵盤的出現而上移(僅限網頁)?

利用dom方法:scrollintoView()。

若是滾動頁面也是DOM沒有解決的一個問題。爲了解決這個問題,瀏覽器實現了一下方法,以方便開發人員如何更好的控制頁面的滾動。在各類專有方法中,HTML5選擇了scrollIntoView()做爲標準方法。scrollIntoView()能夠在全部的HTML元素上調用,經過滾動瀏覽器窗口或某個容器元素,調用元素就能夠出如今視窗中。若是給該方法傳入true做爲參數,或者不傳入任何參數,那麼窗口滾動以後會讓調動元素頂部和視窗頂部儘量齊平。若是傳入false做爲參數,調用元素會盡量所有出如今視口中(可能的話,調用元素的底部會與視口的頂部齊平。)不過頂部不必定齊平.

例子:document.querySelector(".pinlun_input").scrollIntoView(false)    //這是js方法,不要用jquery選擇器執行此方法

相關文章
相關標籤/搜索