深入探究flexiblejs

一、flexiblejs原理

flexiblejs是一款基於淘寶移動端適配方案的自適應方案,在移動端設備中,通過重新計算文檔的根節點字體大小,實現了不同屏幕尺寸下的頁面自適應。

具體來說,它通過以下幾個步驟來實現自適應:

  1. 獲取設備的屏幕寬度,並計算出font-size的大小。
  2. (function(win, lib) {
        var timer,
            doc = win.document,
            docElem = doc.documentElement,
            vpMeta = doc.querySelector('meta[name="viewport"]'),
            flexMeta = doc.querySelector('meta[name="flexible"]'),
            dpr = 0,
            scale = 0,
            tid;
    
    // 獲取設備CSS像素比
        if (vpMeta) {
            console.warn('將根據已有的meta標籤來設置縮放比例');
            var initial = vpMeta.getAttribute('content').match(/initial\-scale=([\d\.]+)/);
            if (initial) {
                scale = parseFloat(initial[1]);
                dpr = parseInt(1 / scale);
            }
        }
    
    // 獲取flexible配置信息
        if (flexMeta) {
            var flex = flexMeta.getAttribute('content');
            if (flex) {
                var arr = flex.split(';');
                for (var i = 0; i  max) {
                                    dpr = max;
                                    scale = parseFloat((1 / dpr).toFixed(2));
                                }
                                break;
                            case 'design-width':
                                lib.designWidth = parseFloat(item[1]);
                                break;
                            case 'maxWidth':
                                lib.maxWidth = parseFloat(item[1]);
                                break;
                            case 'disableScale':
                                lib.disableScale = item[1] === 'true';
                                break;
                        }
                    }
                }
            }
        }
    
    // 設置data-dpr屬性,方便調試
        docElem.setAttribute('data-dpr', dpr);
    
    // 設置viewport
        if (!vpMeta) {
            vpMeta = doc.createElement('meta');
            vpMeta.setAttribute('name', 'viewport');
            vpMeta.setAttribute('content', 'width=device-width, initial-scale=' + scale + ', maximum-scale=' + scale + ', minimum-scale=' + scale + ', user-scalable=no');
            if (docElem.firstElementChild) {
                docElem.firstElementChild.appendChild(vpMeta);
            } else {
                var div = doc.createElement('div');
                div.appendChild(vpMeta);
                doc.write(div.innerHTML);
            }
        } else {
            vpMeta.setAttribute('content', 'width=device-width, initial-scale=' + scale + ', maximum-scale=' + scale + ', minimum-scale=' + scale + ', user-scalable=no');
        }
    
    // 設置根字體大小
        function refreshRem() {
            var width = docElem.getBoundingClientRect().width;
            if (lib.maxWidth && (width / dpr > lib.maxWidth)) {
                width = lib.maxWidth * dpr;
            }
            var rem = width / 10;
            docElem.style.fontSize = rem + 'px';
            lib.rem = win.rem = rem;
        }
    
        win.addEventListener('resize', function() {
            clearTimeout(tid);
            tid = setTimeout(refreshRem, 300);
        }, false);
        win.addEventListener('pageshow', function(e) {
            if (e.persisted) {
                clearTimeout(tid);
                tid = setTimeout(refreshRem, 300);
            }
        }, false);
    
        refreshRem();
    
        lib.dpr = win.dpr = dpr;
        lib.refreshRem = refreshRem;
        lib.rem2px = function(d) {
            var val = parseFloat(d) * this.rem;
            if (typeof d === 'string' && d.match(/rem$/)) {
                val += 'px';
            }
            return val;
        };
        lib.px2rem = function(d) {
            var val = parseFloat(d) / this.rem;
            if (typeof d === 'string' && d.match(/px$/)) {
                val += 'rem';
            }
            return val;
        };
    
    })(window, window['lib'] || (window['lib'] = {}));
    
  3. 設置viewport的meta標籤。
  4. vpMeta.setAttribute('content', 'width=device-width, initial-scale=' + scale + ', maximum-scale=' + scale + ', minimum-scale=' + scale + ', user-scalable=no');
    
  5. 設置根字體大小。
  6. docElem.style.fontSize = rem + 'px';
    

二、flexiblejs還有人用嗎

隨着CSS3的普及,越來越多的開發者開始使用CSS3的媒體查詢來實現移動端適配。不過,flexiblejs依然是一款優秀的適配方案,尤其適用於需要兼容舊設備的場景。它的優點包括:

  • 無需在每個頁面都進行像素單位的轉換,大大提高了開發效率。
  • 支持多種分辨率的設備,頁面表現更加一致。
  • 支持rem和px單位的自由切換。
  • 靈活,可以根據需求進行定製。

三、flexiblejs引入

在引入flexiblejs之前,需要在head區域加入viewport的meta標籤,並去除默認的縮放限制。


然後,在任意一個JS文件中添加以下代碼即可:

(function(win, lib) {
    // ...
})(window, window['lib'] || (window['lib'] = {}));

四、flexiblejs不用了

在使用flexiblejs的過程中,我們也要注意一些需要避免的坑,比如:

  • 盡量避免使用圖片和視頻等非常大的元素。
  • 避免使用過多的字體樣式。
  • 盡量遵循設計規範,避免過多使用寬度百分比。
  • 不要在樣式表中使用!important,這樣會破壞原本的比例關係。

如果你已經要廢棄flexiblejs,可以單獨在head區域刪除相關的meta標籤,然後手動設置根字體大小即可。

html {
    font-size: 16px;
}

五、flexiblejs的缺點

雖然flexiblejs是一款非常優秀的移動端適配方案,但也有一些缺點:

  • 有時候會出現模糊的問題。
  • 使用rem作為單位,在某些場景下會顯得不夠靈活。
  • 對於在Android4.4以下的系統上,可能會遇到一些兼容性問題。

六、flexiblejs替代方案選取

除了flexiblejs以外,還有一些其他的移動端適配方案,比如:

  • 媒體查詢:這是最傳統的適配方案,通過CSS3的媒體查詢來適配不同尺寸的設備。
  • Bootstrap:這是一款非常流行的響應式框架,可以支持更豐富的頁面布局效果。
  • Viewport units:除了rem以外,還可以使用vw和vh等單位來實現自適應。

綜合性能、兼容性和使用難度等因素,可以按照不同項目的需要來選擇適當的方案。

原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-hant/n/270044.html

(0)
打賞 微信掃一掃 微信掃一掃 支付寶掃一掃 支付寶掃一掃
小藍的頭像小藍
上一篇 2024-12-16 13:35
下一篇 2024-12-16 13:35

相關推薦

  • 深入解析Vue3 defineExpose

    Vue 3在開發過程中引入了新的API `defineExpose`。在以前的版本中,我們經常使用 `$attrs` 和` $listeners` 實現父組件與子組件之間的通信,但…

    編程 2025-04-25
  • 深入理解byte轉int

    一、字節與比特 在討論byte轉int之前,我們需要了解字節和比特的概念。字節是計算機存儲單位的一種,通常表示8個比特(bit),即1字節=8比特。比特是計算機中最小的數據單位,是…

    編程 2025-04-25
  • 深入理解Flutter StreamBuilder

    一、什麼是Flutter StreamBuilder? Flutter StreamBuilder是Flutter框架中的一個內置小部件,它可以監測數據流(Stream)中數據的變…

    編程 2025-04-25
  • 深入探討OpenCV版本

    OpenCV是一個用於計算機視覺應用程序的開源庫。它是由英特爾公司創建的,現已由Willow Garage管理。OpenCV旨在提供一個易於使用的計算機視覺和機器學習基礎架構,以實…

    編程 2025-04-25
  • 深入了解scala-maven-plugin

    一、簡介 Scala-maven-plugin 是一個創造和管理 Scala 項目的maven插件,它可以自動生成基本項目結構、依賴配置、Scala文件等。使用它可以使我們專註於代…

    編程 2025-04-25
  • 深入了解LaTeX的腳註(latexfootnote)

    一、基本介紹 LaTeX作為一種排版軟件,具有各種各樣的功能,其中腳註(footnote)是一個十分重要的功能之一。在LaTeX中,腳註是用命令latexfootnote來實現的。…

    編程 2025-04-25
  • 深入理解Python字符串r

    一、r字符串的基本概念 r字符串(raw字符串)是指在Python中,以字母r為前綴的字符串。r字符串中的反斜杠(\)不會被轉義,而是被當作普通字符處理,這使得r字符串可以非常方便…

    編程 2025-04-25
  • 深入了解Python包

    一、包的概念 Python中一個程序就是一個模塊,而一個模塊可以引入另一個模塊,這樣就形成了包。包就是有多個模塊組成的一個大模塊,也可以看做是一個文件夾。包可以有效地組織代碼和數據…

    編程 2025-04-25
  • 深入探討馮諾依曼原理

    一、原理概述 馮諾依曼原理,又稱“存儲程序控制原理”,是指計算機的程序和數據都存儲在同一個存儲器中,並且通過一個統一的總線來傳輸數據。這個原理的提出,是計算機科學發展中的重大進展,…

    編程 2025-04-25
  • 深入剖析MapStruct未生成實現類問題

    一、MapStruct簡介 MapStruct是一個Java bean映射器,它通過註解和代碼生成來在Java bean之間轉換成本類代碼,實現類型安全,簡單而不失靈活。 作為一個…

    編程 2025-04-25

發表回復

登錄後才能評論