tt二面準(zhǔn)備2018-05-17

二面

1. 給一個(gè)數(shù)組排序+去重

去重:

  let set = new Set(arr);
  let result = [...set];

2. js寫(xiě)一個(gè)觀察者模式

https://blog.csdn.net/q1056843325/article/details/53353850

let Event = (function(){
    let clientList = {},
        listen,
        trigger,
        remove;
    listen = function(key, fn) {
        if (!clientList[key]) {
            clientList[key] = [];
        }
        clientList[key].push(fn);
    }

    trigger = function () {
        let key = Array.prototype.shift.call(arguments),
            fns = clientList[key];
        if (!fns || fns.length==0) {
            return false;
        }
        for (let i=0; i<fns.length; i++) {
            let fn = fns[i];
            fn.apply(this, arguments);
        }
    }

    remove = function (key, fn) {
        let fns = clientList[key];
        if (!fns) {
            return false;
        }
        if (!fn) {
            fns && (fns.length = 0);
        } else {
            for (let i=fns.length-1; i>=0; i--) {
                let _fn = fns[i];
                if (_fn == fn) {
                    fns.splice(i, 1);
                }
            }
        }
    }

    return {
        listen,
        trigger,
        remove
    }
)();
Event.listen('squareMeter88', function(price){   //小紅訂閱消息
  console.log('價(jià)格= ' + price);   //輸出:'價(jià)格=2000000'
});
Event.trigger('squareMeter88', 2000000); //售樓處發(fā)布消息

3. 假設(shè)要綜合cpu,gpu給一個(gè)手機(jī)性能做評(píng)價(jià),怎么做

4. js實(shí)現(xiàn)雙向綁定

發(fā)布訂閱模式,使用PubSub
https://www.cnblogs.com/wilber2013/p/5811810.html
源代碼:
https://github.com/WilberTian/Two-way-data-binding/tree/master/1.PubSub
實(shí)現(xiàn)數(shù)據(jù)雙向綁定最直接的方式就是使用PubSub模式:

當(dāng)model發(fā)生改變的時(shí)候,觸發(fā)Model change事件,然后通過(guò)響應(yīng)的事件處理函數(shù)更新界面
當(dāng)界面更新的時(shí)候,觸發(fā)UI change事件, 然后通過(guò)相應(yīng)的事件處理函數(shù)更新Model,以及綁定在Model上的其他界面控件
根據(jù)這個(gè)思路,可以定義'ui-update-event'和'model-update-event'兩個(gè)事件,然后針對(duì)Model和UI分別進(jìn)行這兩個(gè)事件訂閱和發(fā)布。

  • UI更新

對(duì)于所有支持雙向綁定的頁(yè)面控件,當(dāng)控件的“值”發(fā)生改變的時(shí)候,就觸發(fā)'ui-update-event',然后通過(guò)事件處理函數(shù)更新Model,以及綁定在Model上的其他界面控件

處理控件“值”的改變,發(fā)布“ui-update-event”事件,(這里只處理包含“t-binding”屬性的控件):

// keyup和change事件處理函數(shù)
function pageElementEventHandler(e) {
    var target = e.target || e.srcElemnt;
    var fullPropName = target.getAttribute('t-binding');

    if(fullPropName && fullPropName !== '') {
        Pubsub.publish('ui-update-event', fullPropName, target.value);
    }

}

// 在頁(yè)面上添加keyup和change的listener
if(document.addEventListener) {
    document.addEventListener('keyup', pageElementEventHandler, false);
    document.addEventListener('change', pageElementEventHandler, false);
} else {
    document.attachEvent('onkeyup', pageElementEventHandler);
    document.attachEvent('onchange', pageElementEventHandler);
} 

另外,對(duì)所有包含“t-binding”屬性的控件都訂閱了“'model-update-event”,也就是當(dāng)Model變化的時(shí)候會(huì)收到相應(yīng)的通知:

// 訂閱model-update-event事件, 根據(jù)Model對(duì)象的變化更新相關(guān)的UI
Pubsub.subscrib('model-update-event', function(fullPropName, propValue) {   
    var elements = document.querySelectorAll('[t-binding="' + fullPropName + '"]');

    for(var i = 0, len =elements.length; i < len; i++){
        var elementType = elements[i].tagName.toLowerCase();

        if(elementType === 'input' || elementType === 'textarea' || elementType === 'select') {
            elements[i].value = propValue;
        } else {
            elements[i].innerHTML = propValue;
        }

    }
});    
  • Model更新
對(duì)于Model這一層,當(dāng)Model發(fā)生改變的時(shí)候,會(huì)發(fā)布“model-update-event”:
            
// Model對(duì)象更新方法,更新對(duì)象的同時(shí)發(fā)布model-update-event事件
'updateModelData': function(propName, propValue) {    
    eval(this.modelName)[propName] =propValue;   
    Pubsub.publish('model-update-event', this.modelName + '.' + propName, propValue);
}

另外,Model訂閱了“ui-update-event”,相應(yīng)的界面改動(dòng)會(huì)更新Model

// 訂閱ui-update-event事件, 將UI的變化對(duì)應(yīng)的更新Model對(duì)象
Pubsub.subscrib('ui-update-event', function(fullPropName, propValue) {
    var propPathArr = fullPropName.split('.');
    self.updateModelData(propPathArr[1], propValue);
});

5. 移動(dòng)端適配怎么做

react-responsive 不同的MediaQuery適配不同寬度。 部署的時(shí)候打開(kāi)不同的地址(m.taobao.com和taobao.com)

6. 移動(dòng)端點(diǎn)透問(wèn)題

https://segmentfault.com/a/1190000003848737
手機(jī)上的觸摸事件touchstart -> touchmove -> touchend
PC端綁定click, 手機(jī)頁(yè)面綁定tap。
手機(jī)同樣能響應(yīng)鼠標(biāo)mouse事件,但是:

image

可以看到,當(dāng)手觸碰屏幕時(shí),要過(guò)300ms才會(huì)觸發(fā)mousedown事件,所以click事件在手機(jī)上看起來(lái)就像慢半拍一樣。這是因?yàn)闉g覽器在touchend后要判斷用戶是否有雙擊(double tap)行為。如果沒(méi)有,則觸發(fā)click事件,由此可以看出click事件觸發(fā)代表一輪觸摸事件的結(jié)束。
image

整個(gè)容器里有一個(gè)底層元素的div,和一個(gè)彈出層div,為了讓彈出層有模態(tài)框的效果,我又加了一個(gè)遮罩層。

<div class="container">
    <div id="underLayer">底層元素</div>

    <div id="popupLayer">
        <div class="layer-title">彈出層</div>
        <div class="layer-action">
            <button class="btn" id="closePopup">關(guān)閉</button>
        </div>
    </div>
</div>
<div id="bgMask"></div>

然后為底層元素綁定 click 事件,而彈出層的關(guān)閉按鈕綁定 tap 事件。

$('#closePopup').on('tap', function(e){
    $('#popupLayer').hide();
    $('#bgMask').hide();
});

$('#underLayer').on('click', function(){
    alert('underLayer clicked');
});

點(diǎn)擊關(guān)閉按鈕,touchend首先觸發(fā)tap,彈出層和遮罩就被隱藏了。touchend后繼續(xù)等待300ms發(fā)現(xiàn)沒(méi)有其他行為了,則繼續(xù)觸發(fā)click,由于這時(shí)彈出層已經(jīng)消失,所以當(dāng)前click事件的target就在底層元素上,于是就alert內(nèi)容。整個(gè)事件觸發(fā)過(guò)程為 touchend -> tap -> click。

而由于click事件的滯后性(300ms),在這300ms內(nèi)上層元素隱藏或消失了,下層同樣位置的DOM元素觸發(fā)了click事件(如果是input框則會(huì)觸發(fā)focus事件),看起來(lái)就像點(diǎn)擊的target“穿透”到下層去了。

穿透的解決辦法

1. 遮擋

由于 click 事件的滯后性,在這段時(shí)間內(nèi)原來(lái)點(diǎn)擊的元素消失了,于是便“穿透”了。因此我們順著這個(gè)思路就想到,可以給元素的消失做一個(gè)fade效果,類似jQuery里的fadeOut,并設(shè)置動(dòng)畫(huà)duration大于300ms,這樣當(dāng)延遲的 click 觸發(fā)時(shí),就不會(huì)“穿透”到下方的元素了。

同樣的道理,不用延時(shí)動(dòng)畫(huà),我們還可以動(dòng)態(tài)地在觸摸位置生成一個(gè)透明的元素,這樣當(dāng)上層元素消失而延遲的click來(lái)到時(shí),它點(diǎn)擊到的是那個(gè)透明的元素,也不會(huì)“穿透”到底下。在一定的timeout后再將生成的透明元素移除。具體可見(jiàn)demo

2. pointer-events

pointer-events是CSS3中的屬性,它有很多取值,有用的主要是autonone,其他屬性值為SVG服務(wù)。

取值 含義
auto 效果和沒(méi)有定義 pointer-events 屬性相同,鼠標(biāo)不會(huì)穿透當(dāng)前層。
none 元素不再是鼠標(biāo)事件的目標(biāo),鼠標(biāo)不再監(jiān)聽(tīng)當(dāng)前層而去監(jiān)聽(tīng)下面的層中的元素。但是如果它的子元素設(shè)置了pointer-events為其它值,比如auto,鼠標(biāo)還是會(huì)監(jiān)聽(tīng)這個(gè)子元素的。

關(guān)于使用 pointer-events 后的事件冒泡,有人做了個(gè)實(shí)驗(yàn),見(jiàn)代碼

因此解決“穿透”的辦法就很簡(jiǎn)單,demo如下

$('#closePopup').on('tap', function(e){
    $('#popupLayer').hide();
    $('#bgMask').hide();

    $('#underLayer').css('pointer-events', 'none');

    setTimeout(function(){
        $('#underLayer').css('pointer-events', 'auto');
    }, 400);
});

3. fastclick

使用fastclick庫(kù),其實(shí)現(xiàn)思路是,取消 click 事件(參看源碼 164-173 行),用 touchend 模擬快速點(diǎn)擊行為(參看源碼 521-610 行)。

FastClick.attach(document.body);

從此所有點(diǎn)擊事件都使用click,不會(huì)出現(xiàn)“穿透”的問(wèn)題,并且沒(méi)有300ms的延遲。解決穿透的demo

有人(葉小釵)對(duì)事件機(jī)制做了詳細(xì)的剖析,循循善誘,并剖析了fastclick的源碼以自己模擬事件的創(chuàng)建。請(qǐng)看這篇文章,看完后一定會(huì)對(duì)移動(dòng)端的事件有更深的了解

7. 移動(dòng)端300ms延遲怎么解決

http://web.jobbole.com/86114/
方案二:更改默認(rèn)的視口寬度
一開(kāi)始,為了讓桌面站點(diǎn)能在移動(dòng)端瀏覽器正常顯示,移動(dòng)端瀏覽器默認(rèn)的視口寬度并不等于設(shè)備瀏覽器視窗寬度,而是要比設(shè)備瀏覽器視窗寬度大,通常是980px。我們可以通過(guò)以下標(biāo)簽來(lái)設(shè)置視口寬度為設(shè)備寬度。

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

因?yàn)殡p擊縮放主要是用來(lái)改善桌面站點(diǎn)在移動(dòng)端瀏覽體驗(yàn)的,而隨著響應(yīng)式設(shè)計(jì)的普及,很多站點(diǎn)都已經(jīng)對(duì)移動(dòng)端坐過(guò)適配和優(yōu)化了,這個(gè)時(shí)候就不需要雙擊縮放了,如果能夠識(shí)別出一個(gè)網(wǎng)站是響應(yīng)式的網(wǎng)站,那么移動(dòng)端瀏覽器就可以自動(dòng)禁掉默認(rèn)的雙擊縮放行為并且去掉300ms的點(diǎn)擊延遲。如果設(shè)置了上述meta標(biāo)簽,那瀏覽器就可以認(rèn)為該網(wǎng)站已經(jīng)對(duì)移動(dòng)端做過(guò)了適配和優(yōu)化,就無(wú)需雙擊縮放操作了。
這個(gè)方案相比方案一的好處在于,它沒(méi)有完全禁用縮放,而只是禁用了瀏覽器默認(rèn)的雙擊縮放行為,但用戶仍然可以通過(guò)雙指縮放操作來(lái)縮放頁(yè)面。

方案二:FastClick
FastClickFT Labs 專門(mén)為解決移動(dòng)端瀏覽器 300 毫秒點(diǎn)擊延遲問(wèn)題所開(kāi)發(fā)的一個(gè)輕量級(jí)的庫(kù)。FastClick的實(shí)現(xiàn)原理是在檢測(cè)到touchend事件的時(shí)候,會(huì)通過(guò)DOM自定義事件立即出發(fā)模擬一個(gè)click事件,并把瀏覽器在300ms之后的click事件阻止掉。

8. nodejs的事件循環(huán)和瀏覽器的事件循環(huán)有何不同

https://ruiming.me/event-loop-in-nodejs-and-browser/

image

nodejs 和 chrome 的事件驅(qū)動(dòng)實(shí)現(xiàn)上:
node.js 事件由 libuv 驅(qū)動(dòng),chrome 由 webkit 實(shí)現(xiàn)。

瀏覽器的事件循環(huán):https://segmentfault.com/a/1190000010622146

現(xiàn)在我們知道了。在事件循環(huán)中,用戶代理會(huì)不斷從task隊(duì)列中按順序取task執(zhí)行,每執(zhí)行完一個(gè)task都會(huì)檢查microtask隊(duì)列是否為空(執(zhí)行完一個(gè)task的具體標(biāo)志是函數(shù)執(zhí)行棧為空),如果不為空則會(huì)一次性執(zhí)行完所有microtask。然后再進(jìn)入下一個(gè)循環(huán)去task隊(duì)列中取下一個(gè)task執(zhí)行...

那么哪些行為屬于task或者microtask呢?標(biāo)準(zhǔn)沒(méi)有闡述,但各種技術(shù)文章總結(jié)都如下:

  • macrotasks: script(整體代碼), setTimeout, setInterval, setImmediate, I/O, UI rendering
  • microtasks: process.nextTick, Promises, Object.observe(廢棄), MutationObserver
console.log('script start');

setTimeout(function() {
  console.log('setTimeout');
}, 0);

Promise.resolve().then(function() {
  console.log('promise1');
}).then(function() {
  console.log('promise2');
});

console.log('script end');

(代碼來(lái)自Tasks, microtasks, queues and schedules推薦觀看原文的代碼可視化執(zhí)行步驟

如果你測(cè)試的瀏覽器支持的Promise不支持Promise/A+標(biāo)準(zhǔn),或是你使用了其他Promise polfill,運(yùn)行結(jié)果可能有差異。

運(yùn)行結(jié)果是:

script start
script end
promise1
promise2
setTimeout

解釋一下過(guò)程。

  1. 一開(kāi)始task隊(duì)列中只有script,則script中所有函數(shù)放入函數(shù)執(zhí)行棧執(zhí)行,代碼按順序執(zhí)行。
    接著遇到了setTimeout,它的作用是0ms后將回調(diào)函數(shù)放入task隊(duì)列中,也就是說(shuō)這個(gè)函數(shù)將在下一個(gè)事件循環(huán)中執(zhí)行(注意這時(shí)候setTimeout執(zhí)行完畢就返回了)。
  2. 接著遇到了Promise,按照前面所述Promise屬于microtask,所以第一個(gè).then()會(huì)放入microtask隊(duì)列。
  3. 當(dāng)所有script代碼執(zhí)行完畢后,此時(shí)函數(shù)執(zhí)行棧為空。開(kāi)始檢查microtask隊(duì)列,此時(shí)隊(duì)列不為空,執(zhí)行.then()的回調(diào)函數(shù)輸出'promise1',由于.then()返回的依然是promise,所以第二個(gè).then()會(huì)放入microtask隊(duì)列繼續(xù)執(zhí)行,輸出'promise2'。
  4. 此時(shí)microtask隊(duì)列為空了,進(jìn)入下一個(gè)事件循環(huán),檢查task隊(duì)列發(fā)現(xiàn)了setTimeout的回調(diào)函數(shù),立即執(zhí)行回調(diào)函數(shù)輸出'setTimeout',代碼執(zhí)行完畢。
Node的事件循環(huán):http://www.itdecent.cn/p/55546b28cafc

9. 如何做的服務(wù)器端緩存

https://www.cnblogs.com/kevingrace/p/6198287.html
web緩存位于內(nèi)容源Web服務(wù)器和客戶端之間,當(dāng)用戶訪問(wèn)一個(gè)URL時(shí),Web緩存服務(wù)器會(huì)去后端Web源服務(wù)器取回要輸出的內(nèi)容,然后,當(dāng)下一個(gè)請(qǐng)求到來(lái)時(shí),如果訪問(wèn)的是相同的URL,Web緩存服務(wù)器直接輸出內(nèi)容給客戶端,而不是向源服務(wù)器再次發(fā)送請(qǐng)求.Web緩存降低了內(nèi)容源Web服務(wù)器,數(shù)據(jù)庫(kù)的負(fù)載,減少了網(wǎng)絡(luò)延遲,提高了用戶訪問(wèn)的響應(yīng)速度,增強(qiáng)了用戶體驗(yàn).
Nginx: proxy_cache和fastcgi_cache
proxy_cache相關(guān)指令集

(1)proxy_cache指令

語(yǔ)法: proxy_cache zone_name ;
該指令用于設(shè)置哪個(gè)緩存區(qū)將被使用,zone_name的值為proxy_cache_path指令創(chuàng)建的緩存區(qū)的名稱。proxy_pass 指定獲取靜態(tài)內(nèi)容的地址,其實(shí)proxy_cache的原理就是從一個(gè)指定的地址獲取內(nèi)容,然后緩存。當(dāng)下次訪問(wèn)時(shí),nginx會(huì)自動(dòng)判斷有沒(méi)有緩存文件?如果有的話緩存文件是不是已經(jīng)過(guò)期。

(2)proxy_cache_path指令

語(yǔ)法 proxy_cache_path path [levels=number]

keys_zone=zone_name:zone_size[inactive=time] [max_size=size];
該指令用于設(shè)置緩存文件的存放路徑.

例如:
proxy_cache_path /usr/local/nginx/proxy_cache_dir levels=1:2 keys_zone=cache_one:500m inactive=1d max_size=30g ;
解釋:
path 表示存放目錄
levels 表示指定該緩存空間有兩層hash目錄,第一層目錄為1個(gè)字母,第二層目錄為2個(gè)字母,
保存的文件名會(huì)類似/usr/local/nginx/proxy_cache_dir/c/29/XXXXXX ;
keys_zone參數(shù)用來(lái)為這個(gè)緩存區(qū)起名.
500m 指內(nèi)存緩存空間大小為500MB
inactive的1d指如果緩存數(shù)據(jù)在1天內(nèi)沒(méi)有被訪問(wèn),將被刪除。相當(dāng)于expires過(guò)期時(shí)間的配置;
max_size的30g是指硬盤(pán)緩存空間為30G

(3)proxy_cache_methods指令

語(yǔ)法:proxy_cache_methods[GET HEAD POST];
該指令用于設(shè)置緩存哪些HTTP方法,默認(rèn)緩存HTTP GET/HEAD方法,不緩存HTTP POST 方法

(4)proxy_cache_min_uses指令

語(yǔ)法:proxy_cache_min_uses the_number
該指令用于設(shè)置緩存的最小使用次數(shù),默認(rèn)值為1

(5)proxy_cache_valid指令

語(yǔ)法: proxy_cache_valid reply_code [reply_code...] time ;
該指令用于對(duì)不同返回狀態(tài)碼的URL設(shè)置不同的緩存時(shí)間.
例如:
proxy_cache_valid 200 302 10m ;
proxy_cache_valid 404 1m ;
設(shè)置200,302狀態(tài)的URL緩存10分鐘,404狀態(tài)的URL緩存1分鐘.

(6)proxy_cache_key指令

語(yǔ)法: proxy_cache_key line ;
該指令用來(lái)設(shè)置Web緩存的Key值,Nginx根據(jù)Key值md5哈希存儲(chǔ)緩存.一般根據(jù)$host(域名),$request_uri(請(qǐng)求的路徑)等變量組合成proxy_cache_key .

proxy_cache緩存配置的完整示例(多數(shù)nginx緩存的配置):

1)下載nginx和第三方的ngx_cache_purge模塊的編譯安裝包(官網(wǎng):http://labs.frickle.com/nginx_ngx_cache_purge/),將ngx_cache_purge編譯到到Nginx中,用來(lái)清除指定URL的緩存

[root@test-huanqiu ~]# yum install -y pcre pcre-devel openssl openssl-devel gcc //首先安裝依賴
[root@test-huanqiu ~]# cd /usr/local/src
[root@test-huanqiu src]# wget http://labs.frickle.com/files/ngx_cache_purge-2.3.tar.gz
[root@test-huanqiu src]# wget http://nginx.org/download/nginx-1.8.0.tar.gz
[root@test-huanqiu src]# tar -zxvf ngx_cache_purge-2.3.tar.gz
[root@test-huanqiu src]# tar zxvf nginx-1.8.0.tar.gz
[root@test-huanqiu src]# cd nginx-1.8.0.tar.gz
[root@test-huanqiu nginx-1.8.0]# ./configure --user=www --group=www --add-module=../ngx_cache_purge-2.3 --prefix=/usr/local/nginx --with-http_ssl_module --with-http_flv_module --with-http_stub_status_module --with-http_gzip_static_module --with-pcre
[root@test-huanqiu src]# make && make install

2)接著,在同一分區(qū)下創(chuàng)建兩個(gè)緩存目錄,分別供proxy_temp_path , proxy_cache_path指令設(shè)置緩存路徑.

注意:proxy_temp_path和proxy_cache_path指定的路徑必須在同一磁盤(pán)分區(qū),決不能跨區(qū)分,因?yàn)樗鼈冎g是硬鏈接的關(guān)系,避免不通文件系統(tǒng)之間的磁盤(pán)IO消耗。
[root@test-huanqiu src]# mkdir -p /usr/local/nginx/proxy_cache_path #注意,這兩個(gè)目錄的權(quán)限一定要是www.www,即是nginx進(jìn)程權(quán)限
[root@test-huanqiu src]# mkdir -p /usr/local/nginx/proxy_temp_path #這是緩存文件的臨時(shí)存放目錄

3)在配置文件nginx.conf中對(duì)擴(kuò)展名為gif,jpg,jpeg,png,bmp,swf,js,css的圖片,flash,javascript , css文件開(kāi)啟Web緩存,其他文件不緩存。

三面

字符串匹配

正則

Jquery選擇器怎么實(shí)現(xiàn)的

鏈?zhǔn)讲檎?/h3>

介紹項(xiàng)目

二面

1. 自我介紹

2. 介紹一下自己感覺(jué)最有挑戰(zhàn)性的項(xiàng)目。

介紹的思路是先說(shuō)項(xiàng)目性質(zhì)(個(gè)人,社團(tuán)還是實(shí)驗(yàn)室之類的),然后說(shuō)項(xiàng)目規(guī)模(人數(shù),代碼行數(shù)等),再說(shuō)項(xiàng)目架構(gòu),最后說(shuō)自己承擔(dān)的工作。這一部分建議提前做好準(zhǔn)備,對(duì)于項(xiàng)目的亮點(diǎn)和難點(diǎn)都要說(shuō)(自己把握好語(yǔ)速,基本要能說(shuō)20分鐘以上),性能優(yōu)化是非常出彩的地方,一定要重點(diǎn)講。面試官會(huì)在你講完之后問(wèn)一些問(wèn)題,比如當(dāng)時(shí)問(wèn)什么那么做,以及會(huì)和你討論有沒(méi)有更好的做法。問(wèn)的問(wèn)題比較多也比較細(xì),所以一定要說(shuō)自己參與的比較多的項(xiàng)目,事前再熟悉一遍。再后來(lái)問(wèn)了一些我個(gè)人平時(shí)寫(xiě)著玩的小玩意,一個(gè)爬蟲(chóng),一個(gè)原生html+js的小游戲,還有一個(gè)數(shù)學(xué)建模的進(jìn)化論模型。我都詳細(xì)說(shuō)了說(shuō)。

項(xiàng)目性質(zhì):全國(guó)高校云計(jì)算應(yīng)用創(chuàng)新大賽 二等獎(jiǎng)
項(xiàng)目規(guī)模:4人
項(xiàng)目亮點(diǎn)、難點(diǎn):用戶權(quán)限管理、mock
部署:

server
    {
        listen       666;
        server_name 47.92.30.98;
        root  /home/www/antd-admin/dist;

        location /api {
             proxy_pass http://localhost:8000/api;
        }

        location / {
                index  index.html;
                try_files $uri $uri/ /index.html;
        }
    }

版本更新:npm run build:new
依據(jù)package.json中的version字段打包到相應(yīng)目錄,如:當(dāng)前"version":"4.3.0",將會(huì)

  • 更改package.json中的version字段為4.3.1
  • 靜態(tài)文件copy到dist根目錄,版本相關(guān)文件生成到dist/4.3.1目錄
  • dist/index.html將會(huì)引用dist/4.3.1/index.js,所以ngnix配置的時(shí)候只需指向dist/index.html
  • 細(xì)心的觀眾會(huì)發(fā)現(xiàn)dist/4.3.1/index.html,這樣做為了在打包4.3.2后發(fā)現(xiàn)有錯(cuò)誤,還想快速切換至4.3.1,
  • 只需將dist/4.3.1/index.html覆蓋至dist/index.html

version.js做的事

  • 新增版本號(hào),注意只會(huì)增加以“v1.v2.v3”格式的v3的值,如需自定義,自行修改即可
  • 清理最近5個(gè)版本號(hào)以前的文件。

關(guān)于mock:

  • mock的優(yōu)點(diǎn)在于可以在后端未開(kāi)發(fā)接口時(shí),前端可以模擬數(shù)據(jù)接口進(jìn)行開(kāi)發(fā)。

  • roadhog為我們提供了一個(gè)完善的mock功能,在本項(xiàng)目中的接口均為mock的

  • 在開(kāi)發(fā)過(guò)程中,后端部分接口已經(jīng)開(kāi)發(fā)完成,我們?cè)趺词褂脛e人的接口呢?如果需要同時(shí)請(qǐng)求多個(gè)同事的電腦或者多臺(tái)服務(wù)器上的接口呢?我是這樣做的,roadhog的配置中有接口代理的功能(.roadhogrc.js),
    自己mock的接口加上前綴‘/api/v1’,A同事的接口加上前綴‘/api/v2’,C同事的接口加上前綴‘/api/v3’,利用roadhog分別匹配‘/api/v2’,‘/api/v3’并代理到A、B同事的電腦上。這樣就可以不跨域的情況下愉快的開(kāi)發(fā)啦。

  • 當(dāng)發(fā)布到正式環(huán)境后,利用nginx或者其他工具,將‘/api/v1’,‘/api/v2’,‘/api/v3’分別代理到指定的端口或者服務(wù)器,也可以正常運(yùn)行啦

CSS權(quán)重

https://www.w3cplus.com/css/css-specificity-things-you-should-know.html
權(quán)重記憶口訣:從0開(kāi)始,一個(gè)行內(nèi)樣式+1000, 一個(gè)id+100, 一個(gè)屬性選擇器/class或者偽類(:hover, :focus. :visited)+10, 一個(gè)元素名或者偽元素(:after, :before, :first-letter, :first-line, :selection)+1

怎么用CSS實(shí)現(xiàn)一個(gè)正方形

(帶尖角的:https://blog.csdn.net/sunhengzhe/article/details/43675615
如果僅僅是設(shè)置width 和 height的話,這個(gè)問(wèn)題就不用說(shuō)了,這里考慮的問(wèn)題主要是padding的百分比是相對(duì)于誰(shuí)來(lái)說(shuō)的

元素的padding 和 margin百分比都是想對(duì)應(yīng)父元素的width(父元素必須有width這個(gè)值 否則往上查找知道body)來(lái)說(shuō)的, 如下通用的css正方形方案

  • 相對(duì)于父元素width
<!DOCTYPE html>
<html>
  <head>
    <style type="text/css">
      .container {
        width: 100px;
        height: 100px;
      }
      .square {
        width: 100%;
        padding-bottom: 100%;
        background: red;
      }
    </style>
  </head>
  <body>
    <div class="container">
      <div class="square">
      </div>
    </div>
</body>
</html>
  • 可以設(shè)置高度,利用偽元素
<!DOCTYPE html>
<html>
  <head>
    <style type="text/css">
      .square {
        width: 100px;
        background: green;
      }
      .square:after {
        content: '';
        display: block;
        padding-bottom: 100%;
      }
    </style>
  </head>
  <body>
      <div class="square">
      </div>
</body>
</html>

設(shè)置一個(gè)偽元素,偽元素用的是利用 padding-bottom撐起父元素的高度,padding相對(duì)高度為 父元素的 width

  • 不同單位 相對(duì)于視口 而且利用vw
<!DOCTYPE html>
<html>
  <head>
    <style type="text/css">
      .container {
        width: 5%;
        height: 5vw;
        background: red;
      }
    </style>
  </head>
  <body>
    <div class="container">
    </div>
</body>
</html>

CSS值的解析過(guò)程(不是頁(yè)面,是CSS值)

http://jartto.wang/2017/11/13/Exploring-the-principle-of-CSS-parsing/
http://www.nowamagic.net/academy/detail/48110425

image

1.通過(guò)調(diào)用 CSSStyleSheet 的 parseString 函數(shù),將上述 CSS 解析過(guò)程啟動(dòng),解析完一遍后,把 Rule 都存儲(chǔ)在對(duì)應(yīng)的 CSSStyleSheet 對(duì)象中;
2.由于目前規(guī)則依然是不易于處理的,還需要將之轉(zhuǎn)換成 CSSRuleSet。也就是將所有的純樣式規(guī)則存儲(chǔ)在對(duì)應(yīng)的集合當(dāng)中,這種集合的抽象就是 CSSRuleSet;
3.CSSRuleSet 提供了一個(gè) addRulesFromSheet 方法,能將 CSSStyleSheet 中的 rule 轉(zhuǎn)換為 CSSRuleSet 中的 rule ;
4.基于這些個(gè) CSSRuleSet 來(lái)決定每個(gè)頁(yè)面中的元素的樣式;
CSS后問(wèn)的是JS,一個(gè)最基本的[]==true,答這種題的時(shí)候我的方法是先說(shuō)結(jié)論,再說(shuō)理由,如果理由思路清晰而且正確的話,就算結(jié)果是錯(cuò)的問(wèn)題也不大。

CSS語(yǔ)法解析過(guò)程

1.先創(chuàng)建 CSSStyleSheet 對(duì)象。將 CSSStyleSheet 對(duì)象的指針存儲(chǔ)到 CSSParser 對(duì)象中。
2.CSSParser 識(shí)別出一個(gè) simple-selector ,形如 “div” 或者 “.class”。創(chuàng)建一個(gè) CSSParserSelector 對(duì)象。
3.CSSParser 識(shí)別出一個(gè)關(guān)系符和另一個(gè) simple-selector ,那么修改之前創(chuàng)建的 simple-selector, 創(chuàng)建組合關(guān)系符。
4.循環(huán)第3步直至碰到逗號(hào)或者左大括號(hào)。
5.如果碰到逗號(hào),那么取出 CSSParser 的 reuse vector,然后將堆棧尾部的 CSSParserSelector 對(duì)象彈出存入 Vector 中,最后跳轉(zhuǎn)至第2步。如果碰到左大括號(hào),那么跳轉(zhuǎn)至第6步。
6.識(shí)別屬性名稱,將屬性名稱的 hash 值壓入解釋器堆棧。
7.識(shí)別屬性值,創(chuàng)建 CSSParserValue 對(duì)象,并將 CSSParserValue 對(duì)象存入解釋器堆棧。
8.將屬性名稱和屬性值彈出棧,創(chuàng)建 CSSProperty 對(duì)象。并將 CSSProperty 對(duì)象存入 CSSParser 成員變量m_parsedProperties 中。
9.如果識(shí)別處屬性名稱,那么轉(zhuǎn)至第6步。如果識(shí)別右大括號(hào),那么轉(zhuǎn)至第10步。
10.將 reuse vector 從堆棧中彈出,并創(chuàng)建 CSSStyleRule 對(duì)象。CSSStyleRule 對(duì)象的選擇符就是 reuse vector, 樣式值就是 CSSParser 的成員變量 m_parsedProperties 。
11.把 CSSStyleRule 添加到 CSSStyleSheet 中。
12.清空 CSSParser 內(nèi)部緩存結(jié)果。
13.如果沒(méi)有內(nèi)容了,那么結(jié)束。否則跳轉(zhuǎn)值第2步。

()=>{a:1}該箭頭函數(shù)返回值是什么,理由。

http://es6.ruanyifeng.com/#docs/function#箭頭函數(shù)
undefined. 因?yàn)橐硎局苯臃祷匾粋€(gè)對(duì)象應(yīng)該外部用()包圍,{}表示代碼塊。
上面代碼中,原始意圖是返回一個(gè)對(duì)象{ a: 1 },但是由于引擎認(rèn)為大括號(hào)是代碼塊,所以執(zhí)行了一行語(yǔ)句a: 1。這時(shí),a可以被解釋為語(yǔ)句的標(biāo)簽,因此實(shí)際執(zhí)行的語(yǔ)句是1;,然后函數(shù)就結(jié)束了,沒(méi)有返回值。

JSONP

function addScriptTag(src) {
    var script = document.createElement("script");
    script.setAttribute("type", "text/javascript");
    script.src = src;
    document.body.appendChild(script);
}

function myFn (data) {
    alert(data + 'px');  
}

//需要調(diào)用時(shí):
//addScriptTag('b.com/data.aspx?callback=myFn');
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>jsonp</title>
</head>
<body>
    <div id="result"></div>
<script>
(function(window,document,undefined){
var jsonp = function(url,data,callback){
// 回調(diào)函數(shù)+時(shí)間戳
var cbName = 'callback_' + new Date().getTime();
// 暴露全局函數(shù)給window
// 判讀查詢字符串最后一位是否為?或者是&
var queryString = url.indexOf('?') == -1 ? '?' : '&';
// 遍歷傳進(jìn)來(lái)的data實(shí)參賦值給查詢字符串
for(var k in data){
queryString += k + '=' + data[k] + '&';
}
// 查詢字符串加上回調(diào)函數(shù)
queryString += 'callback=' + cbName;
// 創(chuàng)建script標(biāo)簽
var ele = document[0].createElement('script');
// 給script標(biāo)簽添加src屬性值
ele.src = url + queryString;
window[cbName] = function(data){
callback(data);
document[0].body.removeChild(ele);
};
// 添加到body尾部
document[0].body.appendChild(ele);
}
//jsonp函數(shù)暴露給window
window.$jsonp = jsonp;
})(window,document,undefined);
</script>
<script>
$jsonp('http://api.douban.com/v2/movie/in_theaters',{
    'count':1
},function(data){
    document.getElementsByTagName('body')[0].innerHTML = JSON.stringify(data);
})
</script>
</body>
</html>
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容