成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

項(xiàng)目總結(jié) 20171226

張金寶 / 2159人閱讀

摘要:借助預(yù)加載圖片詳情文檔地址項(xiàng)目中為了確保頁(yè)面顯示時(shí),圖片已經(jīng)全部加載完畢,因此需要提前加載圖片,加載圖片的過(guò)程使用進(jìn)度條顯示。第二個(gè)參數(shù)表示是否搜索其子目錄。并在同元素或父級(jí)添加了時(shí),元素顯示。

1. 借助require.context預(yù)加載圖片

詳情文檔地址

項(xiàng)目中為了確保頁(yè)面顯示時(shí),圖片已經(jīng)全部加載完畢,因此需要提前加載圖片,加載圖片的過(guò)程使用進(jìn)度條顯示。

在webpack構(gòu)建的項(xiàng)目中,可以使用require.context來(lái)獲取到靜態(tài)資源的地址。語(yǔ)法如下:

require.context(directory, useSubdirectories = false, regExp = /^.//)

第一個(gè)參數(shù)表示要搜索的文件夾目錄,該目錄支持相對(duì)路徑與在配置文件中定義的路徑別名。
第二個(gè)參數(shù)表示是否搜索其子目錄。
第三個(gè)參數(shù)是一個(gè)用來(lái)匹配文件的正則表達(dá)式。

require.context("modules/App", true, /.(png|jpg|jpeg|gif)$/);
// 創(chuàng)建一個(gè)包含App目錄下所有圖片的上下文模塊

可以使用該上下文模塊自帶的keys方法得到路徑組成的數(shù)組。

const images = require.context("modules/App/", true, /.(png|jpeg|jpg|gif)$/);
console.log(images.keys());

效果大概如下圖所示。

得到圖片路徑之后,就可以借助Promise.all來(lái)完成圖片預(yù)加載,確保圖片加載完成之后再渲染頁(yè)面。

Promise.all(images.keys().map(path => {
  const image = new Image();
  image.src = path;
  image.onload = image.onerror = () => {
    resolve();
  }
}))

但是在開(kāi)發(fā)中遇到一個(gè)問(wèn)題,本地頁(yè)面引用的圖片是編譯過(guò)后的圖片地址,并不是相對(duì)路徑,因此如果直接這樣的話會(huì)因此地址不一致而報(bào)錯(cuò)。

解決辦法是在設(shè)置image對(duì)象src屬性時(shí),修改如下:

image.src = images(path);
// images 是由require.context 創(chuàng)建的上下文模塊

打印出images(path)之后的圖片路徑如下:

上面的修復(fù)方式可以使用如下的知識(shí)點(diǎn)來(lái)理解。

const ctx = require.context("modules/App", true, /*.js/);
const table = ctx("./table.js");

// 上面的代碼等價(jià)于
const table = require("modules/App/table.js"); // 使用require引入模塊

參考文檔

當(dāng)還需要從服務(wù)端提前加載其他資源時(shí),可以使用數(shù)組的concat方法一起放入Promise.all中。

Promise.all(images.keys().map(
  // ...
).concat(http.get("/api/v1/summary")))
2. 細(xì)節(jié)優(yōu)化

整個(gè)頁(yè)面的顯示,一共有15頁(yè)構(gòu)成,由于每一頁(yè)的邏輯與效果都有不少差異,因此將每一頁(yè)定義為了一個(gè)組件,最初在引入這些模塊時(shí)很糟糕的這樣做:

import Page00 from "./Page00";
import Page01 from "./Page01";
import Page02 from "./Page02";
import Page03 from "./Page03";
import Page04 from "./Page04";
import Page05 from "./Page05";
import Page06 from "./Page06";
import Page07 from "./Page07";
import Page08 from "./Page08";
import Page09 from "./Page09";
import Page10 from "./Page10";
import Page11 from "./Page11";
import Page12 from "./Page12";
import Page13 from "./Page13";
import Page14 from "./Page14";

// render里也很復(fù)雜

// ...
render() {
  return (
      
        
        
        
        ...
         
      
  )
}

當(dāng)組件更多時(shí),這樣的引入方式自然是不合理的,可以使用循環(huán)的方式來(lái)引入代碼,優(yōu)化如下:

const allPages = [];

for(let i = 0; i < 15; i++) {
  const id = `0${i}`.slice(-2);
  allPages.push(require(`./Page${id}`).default)
}

這樣就將所有的Page組件放在了allPages數(shù)組中。

render里也可以使用map來(lái)渲染。

render() {
  return (
    
{allPages.map(({ id, Component: Page }) => )}
) }
3. 使用高階組件處理公共邏輯

每一個(gè)Page組件中,都有共同的元素或邏輯,包括logo,分享當(dāng)前屏幕截圖按鈕,統(tǒng)計(jì)邏輯,判斷對(duì)應(yīng)頁(yè)面是否顯示等??梢詫⑦@些共用邏輯使用高階組件來(lái)處理以簡(jiǎn)化代碼。

因此定義了withBox組件來(lái)處理它們。

import React from "react";
import logo from "./images/logo.png";
import { sendEvent } from "utils/track";
import share from "./share";

export default function(Wrapped, checkProp) {
  return class NewPage extends React.Component {
    shareScreen = () => {
      const id = this.refs.box.getAttribute("data-page-id");
      this.refs.box.classList.add("will-screenshot");
      setTimeout(() => share.shareScreenshot(), 100);
      setTimeout(() => this.refs.box.classList.remove("will-screenshot"), 1500);

      sendEvent("share-click", "page" + id);
      sendEvent("click", "share-btn");
    };

    render() {
      const { id, className, ...props } = this.props;
      const cls = className ? `page${id} ${className}` : `page${id}`;

      if (!checkProp || (props.info[checkProp] !== null && props.info[checkProp] !== "undefined")) {
        return (
          
); } return null; } }; }
4. 通過(guò)添加/刪除元素的方式統(tǒng)一控制動(dòng)畫(huà)

首先定義一個(gè)class如下,將會(huì)參與動(dòng)畫(huà)的元素(或其父級(jí))都添加該class以隱藏。

.aninode {
  visibility: hidden;
}

并在同元素(或父級(jí))添加了animated時(shí),元素顯示。

.animated {
  &.aninode, .aninode {
    visibility: visible;
  }
}

并在運(yùn)動(dòng)元素的class中添加了animated時(shí),運(yùn)動(dòng)生效,因此定義運(yùn)動(dòng)css時(shí),應(yīng)該這樣做:

.animated {
  &.flyTopIn, .flyTopIn {
    animation-name: flyTopIn;
    animation-duration: 1s;
  }
  /* more */
}

因此,運(yùn)動(dòng)元素在運(yùn)動(dòng)開(kāi)始之前,應(yīng)該保持這樣

需要運(yùn)動(dòng)時(shí),在該元素的class中添加animated即可。

// or

使用sass的循環(huán)語(yǔ)法定義delay樣式

@for $i from 0 through $delay_count {
  .animated .delay#{$i * 100} {
    animation-delay: $i * 100;
    animation-fill-mode: backwards;
  }
}

具體實(shí)現(xiàn)可參考

5. 小數(shù)精度問(wèn)題導(dǎo)致的bug

js的計(jì)算中,經(jīng)常會(huì)遇到小數(shù)精度的問(wèn)題,最初沒(méi)有注意,導(dǎo)致數(shù)據(jù)顯示出了很多問(wèn)題。例如如下計(jì)算結(jié)果

1.099 * 100
109.89999999999999

解決方法如下:

(1.099 * 100).toFixed(2)

6. Promise與setTimeout的寫(xiě)法問(wèn)題

利用setTimeout判斷某個(gè)對(duì)象是否注入成功。

// 錯(cuò)誤寫(xiě)法
export const checkSDK = () => {
    var timer = null;
    const start = Date.now();

    return new Promise((resolve, reject) => {
        if (typeof window.TigerBridge === "object") {
            resolve();
            return;
        }
        if (Date.now() - start <= 5 * 1000) {
            clearTimeout(timer);
            timer = setTimeout(checkSDK, 100);
            return;
        }

        reject();
    })
}


// 正確寫(xiě)法

export const checkBridge = () => {
    var timer = null;
    const start = Date.now();

    function check(resolve, reject) {
        if (typeof window.TigerBridge === "object") {
            resolve();
            return true;
        } 
        if (Date.now() - start <= 5 * 1000) {
            clearTimeout(timer);
            timer = setTimeout(check.bind(null, resolve, reject), 100);
            return;
        }
        reject();
        return false;
    }

    return new Promise((resolve, reject) => check(resolve, reject))
}

本地模擬注入過(guò)程

if (process.env.NODE_ENV != "production") {
    setTimeout(() => {
        window.TigerBridge = {
            getAccessToken: () => {
                return pkg.token;
            },
            isAccountPermissionLimited: () => false
        };
    }, 1600);
}
7. 圖片串行加載優(yōu)化

一次性加載所有圖片會(huì)導(dǎo)致瀏覽器http線程阻塞嚴(yán)重。因此需要稍作優(yōu)化,讓圖片一張一張加載。

// 優(yōu)化前
images.keys().map(path => new Promise(resolve => {
  const image = new Image();
  image.src = images(path);
  image.onload = image.onerror = resolve;
}))

// 優(yōu)化后
images.keys().reduce((cachePromise, path) => cachePromise.then(() => {
  return new Promise(resolve => {
    const image = new Image();
    const complete = () => {
      clearTimeout(timer);
      resolve();
    }
    const timer = setTimeout(complete, 1000);  // 單張圖片最多加載1s
    image.src = images(path);
    image.onload = image.onerror = complete;
  })
}), Promise.resolve());

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/90455.html

相關(guān)文章

  • 記一次Nodejs安全工單的處理過(guò)程_20171226

    摘要:事件原因之前使用開(kāi)發(fā)的一個(gè)網(wǎng)站。事件的處理方法在公司是有專門(mén)的安全組來(lái)做安全這塊兒工作的。第一時(shí)間對(duì)這個(gè)接口進(jìn)行了下線處理,然后評(píng)估了安全的解決方案,再次上線該接口。這些機(jī)器也肯定是經(jīng)過(guò)做特殊的隔離處理的沒(méi)有敏感的公司信息資源。 事件原因: 之前使用Nodejs開(kāi)發(fā)的一個(gè)網(wǎng)站。在網(wǎng)站上有一個(gè)頁(yè)面有個(gè)功能,允許用戶上傳圖片或者粘貼一張圖片鏈接。服務(wù)端讀取用戶上傳的圖片信息或者是請(qǐng)求用戶填...

    gnehc 評(píng)論0 收藏0
  • 【Vue項(xiàng)目總結(jié)項(xiàng)目nginx部署

    摘要:項(xiàng)目開(kāi)發(fā)完成,接下來(lái)是上線,關(guān)于項(xiàng)目的部署,我司前端是部署在服務(wù)器上,關(guān)于的相關(guān)文檔,請(qǐng)自行查閱本文只記錄部署時(shí)碰到的一些問(wèn)題。其他總結(jié)文章常規(guī)打包優(yōu)化方案組件通信處理方案后臺(tái)管理項(xiàng)目總結(jié) 項(xiàng)目開(kāi)發(fā)完成,接下來(lái)是上線,關(guān)于vue項(xiàng)目的部署,我司前端是部署在nginx服務(wù)器上,關(guān)于nginx的相關(guān)文檔,請(qǐng)自行查閱;本文只記錄部署時(shí)碰到的一些問(wèn)題。 打包 vue項(xiàng)目打包后,是生成一系列的靜...

    CntChen 評(píng)論0 收藏0
  • 【經(jīng)驗(yàn)分享】測(cè)試人員如何寫(xiě)總結(jié)

    摘要:參與者項(xiàng)目經(jīng)理產(chǎn)品經(jīng)理開(kāi)發(fā)經(jīng)理測(cè)試經(jīng)理及其它相關(guān)人員。項(xiàng)目上線后問(wèn)題反饋針對(duì)項(xiàng)目客戶反饋問(wèn)題進(jìn)行分析總結(jié),類似缺陷分析,重點(diǎn)總結(jié)遺漏的原因及后需的規(guī)避措施。六匯總整理各部門(mén)總結(jié)并發(fā)布基于測(cè)試總結(jié)過(guò)程中的數(shù)據(jù)分析,我們提出了對(duì)部門(mén)的建議。 最近參與了幾次面試,面試者的簡(jiǎn)歷中都會(huì)提及:需求或者...

    Vixb 評(píng)論0 收藏0
  • 新疆智營(yíng)銷項(xiàng)目總結(jié)

    摘要:需要對(duì)本項(xiàng)目做一個(gè)總結(jié),提醒自己,記得這些問(wèn)題。總結(jié)自己在這個(gè)項(xiàng)目犯得錯(cuò)以及踩的坑,自己在今后的項(xiàng)目將會(huì)注意以下事項(xiàng)了解項(xiàng)目整體需求和結(jié)構(gòu),知道哪些組件會(huì)公用。 新疆智營(yíng)銷項(xiàng)目是我來(lái)到亞信的第一個(gè)項(xiàng)目,項(xiàng)目初期需求分析沒(méi)有參加,接到設(shè)計(jì)圖直接寫(xiě),沒(méi)來(lái)得及系統(tǒng)的了解整個(gè)項(xiàng)目的結(jié)構(gòu),表格組件定下來(lái)之后,表單form的輸入項(xiàng)打算讓郭山專職負(fù)責(zé),后來(lái)情況發(fā)生變化導(dǎo)致表單一塊前后三個(gè)人參與,沒(méi)有...

    monw3c 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

張金寶

|高級(jí)講師

TA的文章

閱讀更多
最新活動(dòng)
閱讀需要支付1元查看
<