移動端適配方案flexible.js
出發點
事故的開始總是有原因的,那思考一下,為什麼使用Flexible?
- [ ] 為了
rem佈局? >> 為什麼要rem佈局 ——> 高度還原 - [ ] 移動端適配? >> 為什麼移動端適配要用
Flexible——> 同等佔比 - [ ] 什麼是移動端適配?
最初點是設計圖的高度還原!!!
以750*1334設計稿(iPhone6)為準,期望每一個設計元件在iPhone6實機上佔比、寬高比都與設計稿顯示一致。
一套代碼又想擴展到其它設備,於是出現了rem佈局
- [ ]
Flexible做了什麼 - [ ]
rem是什麼 - [ ] 如何做到高度還原設計圖的
引入flexible.js
在*.html的<head>標籤中引入<script src="http://g.tbcdn.cn/mtb/lib-flexible/0.3.4/??flexible_css.js,flexible.js"></script>
flexible.js會做以下幾件事:
-
給
*.html添加內聯樣式表- 只是reset一些樣式
-
給
<html>設置[data-dpr=""]屬性、font-size樣式-
[data-dpr=""]屬性- 通過屬性選擇器,設置不同分辨率下的樣式
- 主要是針對字號
-
font-sizerem單位的基準尺寸
-
- 監聽
resize、pageshow事件來重新設置html.style.fontSize - 設置
body.style.fontSize -
定義全局變量window.lib.flexible
window.lib.flexible = { dpr: number, refreshRem: function, rem2px: function, px2rem: function }
Note:HTML中無需設置meta#viewport,flexible.js會根據window.devicePixelRatio的值自動添加meta#viewport。
假設設置如下<meta name="viewport" content="width=device-width, initial-scale=1.0,user-scalable=no,minimum-scale=1.0,maximum-scale=1.0">,不管設備是多少的dpr,flexible.js不再修改該元數據配置,都會強制認為其dpr是你設置的值。
Note:在Flexible中,只對iOS設備進行dpr的判斷,對於Android系列,始終認為其dpr為1
對於Android系列,始終認為其dpr為1?
深入flexible.js的實現,是body#width依據devicePixelRatio進行縮放的。
而針對iOS設備,縮放後正好為其visual viewport的尺寸。
而針對Android系列手頭上的機器測試,不用縮放,body#width正好為其visual viewport的尺寸。
body#width / dpr > 540?
若body#width / dpr > 540,如PC端body#width > 1080,Flexible當1080處理。
通過scss定義px2rem的轉換
~在不使用自動化工具的基礎上,無法使用以下處理方式,只能自己計算後再賦值~
@function px2rem($px, $base-font-size: 16px) {
@if (unitless($px)) {
@warn "Assuming #{$px} to be in pixels, attempting to convert it into pixels for you";
@return px2rem($px + 0px); // That may fail.
} @else if (unit($px) == rem) {
@return $px;
}
@return ($px / $base-font-size) * 1rem;
}
原理:通過以上步驟,就能實現設計圖的高度還原?
本質上是設計元件的同比轉換。
flexible.js將body#width分成100份,一份為基準,設置為html#fontStyle,而px2rem將設計元件轉換為設計圖的佔比*%,以rem為中介,在設備上的展示具有同等佔比。
以此來實現設計圖的高度還原。
然而,計算出來的結果可能非有效值,所以,瀏覽器的顯示優化……
如:小於12px的字體、浮點數的精度……
文本字號不建議使用rem
我們希望文本在相同
dpr屏幕下文本字號相同我們希望在大屏手機上看到更多文本
不希望出現13px和15px這樣的奇葩尺寸
解決方案
文本還是使用px作為單位,只不過使用[data-dpr]屬性來區分不同dpr下的文本字號大小
~在不使用自動化工具的基礎上,無法使用以下處理方式,只能自己計算後再賦值~
@mixin font-dpr($font-size){
font-size: $font-size;
[data-dpr="2"] & {
font-size: $font-size * 2;
}
[data-dpr="3"] & {
font-size: $font-size * 3;
}
}
@include font-dpr(16px);
補充知識點
-
flexible.js使用document.readyState API獲取document的加載狀態document.addEventListener('readystatechange', event => { if (event.target.readyState === 'interactive') { // 等同於DOMContentLoaded 事件 } else if (event.target.readyState === 'complete') { // 表示 load 狀態的事件即將被觸發。 // 等同於loaded } });
在Vue項目中的實戰
~項目由@vue/cli@4.5.13創建的~
移動端適配
引入flexible
-
安裝
lib-flexiblenpm i -D lib-flexible -
項目中引入
flexible# main.js import "lib-flexible/flexible";
Note: 直接在HTML模板的<head>中引用,執行的優先級會更高
樣式px自動轉rem
-
安裝
postcss-plugin-px2remnpm i -D postcss-plugin-px2rem -
創建
.postcssrc.js# .postcssrc.js module.exports = { plugins: { 'postcss-plugin-px2rem': { rootValue: 108, //換算基數,設計圖尺寸, 默認100 exclude: /(node_module)/, //默認false,可以(reg)利用正則表達式排除某些文件夾的方法,例如/(node_module)\/ mediaQuery: false, //(布爾值)允許在媒體查詢中轉換px。 minPixelValue: 3, //設置要替換的最小像素值(3px會被轉rem)。 默認 0 } } } -
凡事有例外
若不想轉換rem,單位使用全大寫PX,如字體# presets.scss $largeFont: 40PX; $middleFont: 20PX; $standardFont: 14PX; $smallFont: 10PX; @mixin font-dpr($font){ font-size: $font; [data-dpr="2"] & { font-size: $font * 2; } [data-dpr="3"] & { font-size: $font * 3; } }# example.scss ... @import "../../assets/scss/preset"; .page-title{ @include font-dpr($standardFont); } ...
規範提交記錄
通過以下命令@vue/cli會自動安裝commitlint插件並更新pkg
vue add commitlint
swiper應用
-
安裝依賴
npm install swiper vue-awesome-swiper --save -
全局註冊
# main.js ... import VueAwesomeSwiper from "vue-awesome-swiper"; import "swiper/swiper.scss"; Vue.use(VueAwesomeSwiper, {}); ... -
邏輯應用
# Example.vue <template> <swiper ref="mySwiper" :options="swiperOptions"> <swiper-slide v-for="i in 5"> <div> Slide {{i}} </div> <button @click="handleClickItem(i)">點擊後才可滑動</button> </swiper-slide> </swiper> </template> <script> export default { name: "Example", data() { return { swiperOptions: { direction: "vertical", }, }; }, methods: { handleClickItem(idx) { // 滿足某條件後可滑動 this.swiper.allowSlideNext = true; }, }, computed: { swiper() { return this.$refs.mySwiper.$swiper; }, }, mounted() { // 默認禁止滑動翻頁 this.swiper.allowSlidePrev = false; this.swiper.allowSlideNext = false; // 翻頁後禁止翻頁 this.swiper.on("slideChange", () => { this.swiper.allowSlideNext = false; this.currentIdx = this.swiper.activeIndex; }); }, }; </script> -
樣式
# example.scss .swiper { &- { &container { height: 100%; } &slide { height: 100%; color: white; } } } button { position: absolute; z-index: 100; bottom: 20PX; width: 100%; text-align: center; }
非標準字體
非標準字體是指人為調整系統設置中的字體字號大小。
(function () {
var $dom = document.createElement("div");
$dom.style = "font-size:20px;";
document.body.appendChild($dom);
// 計算出放大後的字體
var scaledFontSize = parseInt(
window.getComputedStyle($dom, null).getPropertyValue("font-size")
);
document.body.removeChild($dom);
// 計算原字體和放大後字體的比例
var scaleFactor = 20 / scaledFontSize;
// 取html元素的字體大小
// 注意,這個大小也經過縮放了
// 所以下方計算的時候 *scaledFontSize是原來的html字體大小
// 再次 *scaledFontSize才是我們要設置的大小
var originRootFontSize = parseInt(
window
.getComputedStyle(document.documentElement, null)
.getPropertyValue("font-size")
);
document.documentElement.style.fontSize =
originRootFontSize * scaleFactor * scaleFactor + "px";
alert(
parseInt(
window
.getComputedStyle(document.documentElement, null)
.getPropertyValue("font-size")
)
);
})();
上述章節我們説【不推薦】字號使用rem,而使用px,是因為想讓不同設備像素比的設備更大的程度利用展示空間:大屏一行展示的文本更多,小屏展示的少一些。
而考慮非標準字體,若字號使用px,即使通過上述方法調整html的基準字號大小,也不會影響字體的展示。
所以,考慮非標準字體時,字號需要使用rem設置。
Pad適配
現在Pad盛行,要考慮適配Pad.
對於Pad的適配,Flexible並沒有考慮,而我們可以稍作修改進行適配。
Flexible並沒有考慮Pad,通過修改var isIPhone = win.navigator.appVersion.match(/iphone|iPad/gi);調整-
Flexible針對設備有最大尺寸限制,將其去掉即可function refreshRem(){ var width = docEl.getBoundingClientRect().width; // if (width / dpr > 540) { // width = 540 * dpr; // } var rem = width / 10; docEl.style.fontSize = rem + 'px'; flexible.rem = win.rem = rem; } -
px2rem的媒體查詢配置- 刪除
postcss-plugin-px2rem插件及其配置 -
自定義px轉rem函數 —— 為了媒體查詢
//# px2rem.scss $defaultFontSize: 108; @function px2rem($px, $baseFontSize: $defaultFontSize) { @return $px / $baseFontSize * 1rem; }
.main { width: px2rem(540); @media screen and (min-width: 450px) { width: px2rem(1660, 166); } } - 刪除
參考文檔
- 阿里移動端知識儲備
- Flexible官方文檔
viewport的介紹1viewport的介紹2- iphone12適配
- swiper相關配置
- 非標準字體