Next框架與主流工具的整合(二)—— 完善與優化

前言:18年12月24日項目成功上線了,在經歷了兩週的線上bug、UI以及代碼優化後,解決了很多問題,因而再完善與優化一下這個 項目
  • 佈局優化
  • 高清配置
  • antd-mobile 自定義配置
  • antd-mobile Toast組件封裝

佈局優化

佈局優化在這篇文章完成了 → [移動端優雅佈局實踐](),最後我使用的方案是——absolute脫離文檔流(好處是設置容器的height: 100%,能夠直接繼承html窗口高度)。javascript

高清配置

問題發現

開始項目以前沒有對dpr(device pixel radio)與縮放作過多的瞭解,在項目開發的時候就將它們都直接寫死爲1了。到後來UI驗收的時候發現並無實現UI設計師預期的細線效果。我在解決這個問題的時候纔去認真看了一下dpr的介紹。這篇詳解dpr的文章寫得還不錯。css

從概念來講,dpr就是設備的物理像素與設備獨立像素(也就是css邏輯像素,如下就稱爲css邏輯像素)的比率。html

好比:iPhone 6的分辨率是750*1334,window.screen.width(css邏輯像素)爲375,所以java

dpr = 750 /375 = 2

再好比:iPhone X的分辨率是1125*2436,window.screen.width(css邏輯像素)也是375,所以node

dpr = 1125 /375 = 3

那麼dpr有什麼用呢?react

在這以前先提一下咱們移動端必備的一個meta標籤:webpack

<meta name="viewport" content="width=device-width,maximum-scale=1,minimum-scale=1,user-scalable=no" />
device-width在html中也一樣被解讀爲理想(基準)視口的寬度,即320px,375px,414px,這裏的px就是指css像素,一般也被稱爲邏輯像素;那咱們能夠認爲html中的css像素的顯示尺寸應該和NA中的pt、dp的顯示尺寸相等。

經過這個meta標籤,咱們能夠實現initial-scale=1初始縮放100%,就能夠達到1px的css邏輯像素 = 眼睛在設備上看起來的1px,換句話說body { width: 375px; }能夠在iPhone 6上充滿豎屏的整個寬度git

那麼問題就來了,若是咱們要給一個盒子加上一個1px的細線:
border-bottom: 1px solid red;。那麼在iPhone 6上真的是1px嗎?github

iPhone 6真機截圖(寬度爲702px):
imageweb

能夠看出高度明顯不止1像素。這就是因爲dpr形成的,由於iPhone 6的dpr爲2,且縮放比例爲100%,1px的css渲染出來就是2px物理像素。

這就是咱們UI粑粑和產品們不滿意的地方。

那接下來如何去解決這個問題呢?

解決方案

根據設備的dpr來動態計算縮放比例,以及根節點的font-size

// rem.js
(function(doc, win) {
  var docEl = doc.documentElement,
    dpr = Math.min(win.devicePixelRatio, 3);
  dpr = window.top === window.self ? dpr : 1; //被iframe引用時,禁止縮放
  var scale = 1 / dpr,
    resizeEvt = 'orientationchange' in window ? 'orientationchange' : 'resize';
  docEl.dataset.dpr = dpr;
  var metaEl = doc.createElement('meta');
  metaEl.name = 'viewport';
  metaEl.content =
    'initial-scale=' +
    scale +
    ',maximum-scale=' +
    scale +
    ', minimum-scale=' +
    scale +
    ',user-scalable=no,viewport-fit=cover';
  docEl.firstElementChild.appendChild(metaEl);
  var recalc = function() {
    var width = docEl.clientWidth;
    // 大於1280按1280來算
    if (width / dpr > 1280) {
      width = 1280 * dpr;
    }
    // px : rem = 100 : 1
    docEl.style.fontSize = 100 * (width / 375) + 'px';
  };
  recalc();
  if (!doc.addEventListener) return;
  win.addEventListener(resizeEvt, recalc, false);
})(document, window);
若是有顯示富文本元素,則須要處理富文本元素的樣式

移動端爲了適配不一樣的機型,使用rem爲單位是一個不錯的選擇,並且咱們也一直在用它。

這裏除了根據dpr來計算initial-scale,還調整了根節點的font-size,以致於在縮放的時候可以還原到視窗大小(由於要縮放,因此要相應的增長rem的基數)。

這樣咱們上面寫的border-bottom: 1px solid red;在這個方案顯示出來就是這樣的:
image

哇咔咔,能夠看出明顯變細了,這纔是咱們UI粑粑們想要的O(∩_∩)O~~

可是這樣的設置在結合ant-design-mobile的時候,發現ant-design-mobile的組件都被縮小了。原來是,它的元素都是以px爲單位,而咱們縮放前沒有對它的最小單位乘以相應的基數。那麼,咱們須要給它配置一個基數

antd-mobile自定義配置

查文檔發現ant-design-mobile提供了主題配置,並且它提供了一個@hd的變量作爲長度基本單位,它的默認值是1px

咱們只須要把@hd設置爲0.01rem就能夠解決問題。

這個主題配置的文檔是以webpack項目來作的例子。那如何在next.js項目中完成自定義配置呢?

我在next.js的examples中沒有找到我所須要的example,不過找到了兩個相關的例子:一個是with-antd-mobile,一個是with-ant-design-less。第二個是ant-design的自定義主題配置,那應該就能夠仿照這個example去增長with-antd-mobile的自定義主題配置。

這裏提一下,這個 with-antd-mobile在我寫 Next框架與主流工具的整合以後更新了 next.config.js的配置,這裏也改爲了最新的配置。
  1. 安裝解析 Lessnormalize.css 的包
npm i @zeit/next-less @zeit/next-css less less-vars-to-js -S
  1. 修改.babelrc配置
{
  "presets": ["next/babel"],
  "plugins": [
    [
      "import",
      {
        "libraryName": "antd-mobile",
        "style": true
      }
    ]
  ]
}
  1. 修改next.config.js配置
/* eslint-disable */
const withCSS = require('@zeit/next-css');
const withSass = require('@zeit/next-sass');
const withLess = require('@zeit/next-less');
const lessToJS = require('less-vars-to-js');
const fs = require('fs');
const path = require('path');

// Where your antd-custom.less file lives
const themeVariables = lessToJS(fs.readFileSync(path.resolve(__dirname, './antd-custom.less'), 'utf8'));

// fix: prevents error when .less files are required by node
if (typeof require !== 'undefined') {
  require.extensions['.less'] = file => {};
  require.extensions['.css'] = file => {};
}

module.exports = withCSS(
  withLess(
    withSass({
      lessLoaderOptions: {
        javascriptEnabled: true,
        modifyVars: themeVariables
      }
    })
  )
);
  1. 在項目下新建Less變量文件 antd-custom.less
@hd: 0.01rem;

重啓項目,就大功告成了。

antd-mobile Toast組件封裝

antd-mobileToast.info()組件在顯示的時候不能點擊背景就消失,與原生的Toast有些差別,爲了體驗,這裏再作了一層封裝,在點擊背景的時候隱藏Toast。

// utils/toast.js
static info = (content, duration, onClose, mask) => {
    Toast.info(content, duration, onClose, mask);
    const toastElement = document.getElementsByClassName('am-toast-mask')[0];
    toastElement &&
      toastElement.addEventListener('click', () => {
        Toast.hide();
        onClose && onClose();
      });
  };

antd-mobile的loading圖在Android上有些怪異,這裏也自定義了Loading:

static loading = (content, duration, onClose, mask) => {
    Toast.info(
      <div>
        <svg className="rotate360-800" width="0.26rem" height="0.26rem" viewBox="0 0 26 26">
          <title>加載</title>
          <desc>Created with Sketch.</desc>
          <g id="首頁" stroke="none" strokeWidth="1" fill="none" fillRule="evenodd">
            <g transform="translate(-185.000000, -519.000000)" fill="#FFFFFF" id="加載">
              <g transform="translate(185.000000, 519.000000)">
                <g id="分組" transform="translate(0.625011, 0.625011)">
                  <path
                    d="M12.3750144,0.0259531552 C5.53983848,0.0259531552 0,5.56600648 0,12.4009676 C0,19.2359286 5.53983848,24.775982 12.3750144,24.775982 C19.2099755,24.775982 24.7500288,19.2359286 24.7500288,12.4009676 C24.7500288,5.56579163 19.2099755,0.0259531552 12.3750144,0.0259531552 Z M12.3750144,22.028385 C7.05736759,22.028385 2.74781179,17.7185714 2.74781179,12.4009676 C2.74781179,7.08332074 7.05741056,2.7735501 12.3750144,2.7735501 C17.6926612,2.7735501 22.0026467,7.08336371 22.0026467,12.4009676 C22.0026467,17.7186144 17.6926182,22.028385 12.3750144,22.028385 Z"
                    id="形狀"
                    fillOpacity="0.2"
                    fillRule="nonzero"
                  />
                  <path
                    d="M12.3749972,0.0259402646 L12.3750144,2.77353721 C17.6926612,2.77353721 22.0026467,7.08335082 22.0026467,12.4009547 L24.7500116,12.4009547 C24.7500116,5.56577874 19.2099583,0.0259402646 12.3749972,0.0259402646 Z"
                    id="路徑"
                  />
                </g>
              </g>
            </g>
          </g>
        </svg>
        <div style={{ fontSize: '0.12rem' }}>{content}</div>
      </div>,
      duration,
      onClose,
      mask
    );
  };

寫在最後

一個項目須要在不斷的優化與完善中才能變得更好。搭建項目是對一個項目負責人很大的考驗,若是在項目設計的初期有許多的問題沒有考慮到,就頗有可能致使優化的時候須要耗費很大的精力。

總之,不要逃避困難與問題,這些都是成長路上不可或缺的。

相關文章
相關標籤/搜索