掌握面試——彈出框的實現(xiàn)

這道面試題萝风,當(dāng)初我面試的時候被問過兩次嘀掸,因此比較深,此外规惰,我記得還有設(shè)計模式的考察睬塌,所以,有深刻的體會歇万。

面試題主要考察什么

面試不是個輕松的活揩晴,不管是對面試官還是面試者都一樣。對于面試官來說贪磺,別的先不管硫兰,首先一點技術(shù)要過關(guān),對候選人的基本要求就是基礎(chǔ)扎實寒锚,有相關(guān)項目經(jīng)驗劫映,有解決問題的能力,思路清晰壕曼,易于溝通苏研。而對于面試者來說要技術(shù)扎實等浊,知識面要廣腮郊,要有技術(shù)閃光點,對于各種技術(shù)提起來都知道點筹燕,但經(jīng)不起深層次的詢問轧飞,這種‘一瓶子水不滿,半瓶子水晃地’現(xiàn)象很不受面試官的喜歡撒踪。

雖然过咬,我工作的時間不長,但被面試過制妄,也面試過別人掸绞。所以,將這道題被問的情況和自己的體會理解分享給大家耕捞。

注:面試公司 去哪兒衔掸,360

用 html + css 實現(xiàn)一個彈出框

注:這是按照面試官的預(yù)想可能出現(xiàn)的情況設(shè)定的,不同的面試者臨場發(fā)揮不一樣俺抽,面試官可能問的問題也有所變化敞映,但歸根結(jié)底,這個系列的問題大致如下磷斧。

這里你在回答前需要問清楚實現(xiàn)有什么限制沒振愿,如果沒有捷犹,你可以以任意的方式來實現(xiàn);如果有冕末,問清楚限制萍歉,一般限制有如下情況,一種定寬定高档桃,另一種不定寬高(補丁寬高一般用js控制)翠桦,但是使用css3亦可實現(xiàn),如果你回答出一種胳蛮,面試官往往會問有沒有其他的實現(xiàn)方法销凑,如果面試管這樣問了,你如果仅炊,回答沒有斗幼,會被扣分的。面試會進(jìn)入下一個環(huán)節(jié)抚垄。

彈出框垂直水平居中

html:

<div class="box-default box-wh box-vc-mar">this is a pop-up box</div>

css:
.box-default {
position: fixed;
top: 50%;
left: 50%;
z-index: 99;
padding: 20px;
background-color: white;
border: 1px solid #ccc;
border-radius: 8px;
}

.box-wh {
    width: 200px;
    height: 200px;
}

.box-vc-mar {
    margin-left: -100px;
    margin-top: -100px;
}

JSFiddle效果演示

如果彈出窗的寬高不定

html:

<div class="box-default">this is a pop-up box</div>

css:

.box-default {
    position: fixed;
    top: 50%;
    left: 50%;
    z-index: 99;
    padding: 20px;
    background-color: white;
    border: 1px solid #ccc;
    border-radius: 8px;
}

.box-vc-mar {
    margin-left: -100px;
    margin-top: -100px;
}

js:

var $box = $('.box-default'),
    bw = $box.width(),
    bh = $box.height();
$box.css({
  marginLeft: - bw/2 + 'px',
  marginTop: - bh/2 + 'px',
});

JSFiddle效果演示

有沒有其他方式實現(xiàn)不定寬高的彈出窗

答案:有

html:

<div class="box-default box-vc-trf">this is a pop-up box that only html+css</div>

css:

.box-default {
    position: fixed;
    top: 50%;
    left: 50%;
    z-index: 99;
    padding: 20px;
    background-color: white;
    border: 1px solid #ccc;
    border-radius: 8px;
}

.box-vc-trf {
    -webkit-transform: translate(-50%, -50%);
    -ms-transform: translate(-50%, -50%);
    -o-transform: translate(-50%, -50%);
    transform: translate(-50%, -50%);
}

JSFiddle效果演示

4.如果給彈出窗加一個遮罩層該如何實現(xiàn)

html:

<div class="box-default box-vc-trf">this is a pop-up box that only html+css</div>
<div class="mask"></div>

css:

.box-default {
  position: fixed;
  top: 50%;
  left: 50%;
  z-index: 99;
  padding: 20px;
  background-color: white;
  border: 1px solid #ccc;
  border-radius: 8px;
}
.box-vc-trf {
  -webkit-transform: translate(-50%, -50%);
  -ms-transform: translate(-50%, -50%);
  -o-transform: translate(-50%, -50%);
  transform: translate(-50%, -50%);
}
.mask {
  position: fixed;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  z-index: 98;
  background-color: #000;
  opacity: 0.75;
  filter: alpha(opacity=75);
}

JSFiddle效果演示

下面的問題就問的比較深了蜕窿,牽涉到了一些簡單業(yè)務(wù)實現(xiàn)

觸發(fā)按鈕實現(xiàn)彈窗

根據(jù)是之前實現(xiàn)的結(jié)果,如果在頁面中有一個按鈕呆馁,通過觸發(fā)鈕如何實現(xiàn)彈出窗以及實現(xiàn)關(guān)閉彈出窗

示例代碼如下:

html:

<div class="box-default box-vc-trf">this is a pop-up box that only html+css</div>
<div class="mask"></div>

<button id="btn">click it</button>

css:

.box-default {
  position: fixed;
  top: 50%;
  left: 50%;
  z-index: 99;
  display: none;
  padding: 20px;
  background-color: white;
  border: 1px solid #ccc;
  border-radius: 8px;
}

.box-in {
  display: block;
}

.box-vc-trf {
  -webkit-transform: translate(-50%, -50%);
  -ms-transform: translate(-50%, -50%);
  -o-transform: translate(-50%, -50%);
  transform: translate(-50%, -50%);
}

.mask {
  position: fixed;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  z-index: 98;
  display: none;
  background-color: #000;
  opacity: 0.75;
  filter: alpha(opacity=75);
}

.mask-in {
  display: block;
}

js:

var $box = $('.box-default'),
    $mask = $('.mask'),
    $btn = $('#btn');

$btn.on('click', function(event) {
  event.preventDefault();
  $box.addClass('box-in');
  $mask.addClass('mask-in');
});

$mask.on('click', function(event) {
  event.preventDefault();
  $(this).removeClass('mask-in');
  $box.removeClass('box-in');
});

JSFiddle效果演示

這個只是我的實現(xiàn)桐经,每個人的實現(xiàn)都會有所不同。

此外浙滤,像這里如何關(guān)閉彈出窗的實現(xiàn)方式阴挣,并不一定要通過觸發(fā)遮罩層來實現(xiàn),我們常見的實現(xiàn)是在彈出窗中加一個關(guān)閉按鈕纺腊。像在這里這種模棱兩可的地方畔咧,往往存在陷阱,我建議在你給出答案前先問清楚這個關(guān)閉彈出窗要如何實現(xiàn),并給出自己的方案,因為在實際的項目開發(fā)的過程有些細(xì)節(jié)問題產(chǎn)品經(jīng)理并不會面面俱到否副,會有疏漏的地方,而作為一個前端你要及時的提出來拜隧,進(jìn)行溝通確認(rèn),這里可能會考察你的觀察趁仙,判斷和溝通能力洪添。但有些時候你問過后,面試官會對你笑笑幸撕,讓你自由發(fā)揮薇组,你這時就會明白,這是一處坑坐儿。但有時候不是這樣律胀,所以宋光,面試時要主動與面試官溝通,避免因細(xì)節(jié)問題在面試過程中被降分炭菌。

如果在頁面中有多個按鈕罪佳,那么這個彈出窗要如何實現(xiàn)

同上,根據(jù)之前的建議在回答問題之前要問清楚問題中模棱兩可的地方黑低。

1.多個按鈕是不是成百上千個赘艳,或者就是幾個。

2.是否觸發(fā)不同按鈕彈出的窗口現(xiàn)實的內(nèi)容不同克握。

同時也可以不問蕾管,你只要明白要考察的知識點即可,問只是讓你更清楚的知曉面試官的考察點菩暗。

html:

<div class="box-default box-vc-trf">this is a pop-up box that only html+css</div>
<div class="mask"></div>

<button class="btn">click</button>
<button class="btn">click2</button>
<button class="btn">click3</button>
<button class="btn">click4</button>
<button class="btn">click5</button>
<button class="btn">click6</button>

css:

css 同上個示例

js:

$(function(){
    var $box = $('.box-default'),
        $mask = $('.mask');
    
    $mask.on('click', function(event) {
      event.preventDefault();
      hideMask();
    });

    $('.btns').forEach(function(el, i) {
        el.on('click', function(event) {
          event.preventDefault();
          var content = getText($(this));
          showMask(content);
        }
    });

    function getText(obj) {
        return obj.text()
    }

    function showMask(content) {
      $box.addClass('box-in').html(content);
      $mask.addClass('mask-in');
    }

    function hideMask(obj) {
      $mask.removeClass('mask-in');
      $box.removeClass('box-in');
    }
});

這里主要考察了兩點:

1.js基礎(chǔ)是否扎實

  • 表現(xiàn)和行為的分離
  • 可維護(hù)性
  • 可擴展性

2.是否使用了事件代理

代碼修改如下:

$(function(){
    ...

    $(document.body).on('click', '.btn', function(event) {
      event.preventDefault();
      var content = getText($(this));
      showMask(content);
    });

    ...
});

JSFiddle效果演示

有時候面試官會讓你用原生js來實現(xiàn)事件代理掰曾,那么我們應(yīng)該如何回答呢?

由于事件委托可以實現(xiàn)目標(biāo)對象的隱藏停团,在開發(fā)這對于我們保護(hù)一些核心的對象非常有用旷坦,不過實話來說,在JavaScript中就是call佑稠,apply的使用秒梅,因為js中只有這兩個方法提供了改變當(dāng)前函數(shù)內(nèi)部this作用域的功能。當(dāng)然這只是對象的委托舌胶,而要實現(xiàn)對類的委托則要相對復(fù)雜些捆蜀,對類的實現(xiàn)大家有興趣的可以參考以下Prototype.js或Jquery中的相應(yīng)實現(xiàn)。

事件代理就要改變偵聽器的位置辆琅,或者說改變事件綁定的對象漱办。得益于js的事件傳播機制,實現(xiàn)起來非常容易婉烟。

下面這個例子大家都可能見過:

html:

<ul id="nav">
    <li><a >CSDN</a></li>
    <li><a >Segmentdefault</a></li>
    <li><a >github</a></li>
    <li><a >稀土掘金</a></li>
    <li><a >博客園</a></li>
</ul>

js:

window.onload = function(){
  var nav = document.getElementById("nav");
  nav.onclick = function () {
    var e = arguments[0] || window.event,
        target = e.srcElement ? e.srcElement : e.target;
    if (target.nodeName.toLowerCase() === 'a')
        alert(target.innerHTML);
    return false;
  }
}

JSFiddle效果演示

var addEvent = (function () {
    if (document.addEventListener) {
      return function (el, type, fn) {
        el.addEventListener(type, fn, false);
      };
    } else if (document.attachEvent) {
      return function (el, type, fn) {
        el.attachEvent('on' + type, fn);
      }
    } else {
        el['on' + type] = fn
    }
  })();

上面這個事件監(jiān)聽的兼容性代碼片段,是面試官問我是否對jQuery源碼有所了解暇屋,我當(dāng)然說有似袁,就讓我說一下如何實現(xiàn)。

好了咐刨,關(guān)于事件代理的問題就不深入討論了昙衅,我們接著了解關(guān)于彈出窗的其他問題。

遮罩層的共用問題

同一個頁面我們可以考慮定鸟,直接在頁面中加一個表示遮罩層的div而涉,
但是對于不同的頁面我們最好用js來控制。

問題:這里面試管會問联予,如何實現(xiàn)遮罩層的共享啼县?

我們通常會寫下面的一個代碼片段:

function createMask() {
    return $(document.body).append($('<div>').addClass('mask'));
}

雖然材原,這樣添加一個遮罩層,在隱藏的時候可以使用remove()移除它季眷,但顯然這樣在頁面中頻繁的添加余蟹,刪除dom元素不合理。

問題:有沒有什么方法可以對它進(jìn)行優(yōu)化子刮?

我們可能會考慮對它進(jìn)行優(yōu)化威酒,先在全局創(chuàng)建一個這個遮罩層div,用一個變量來引用它挺峡。代碼如下:

var mask = $(document.body).append($('<div>').addClass('mask'));

這樣頁面就只會創(chuàng)建一個遮罩層div葵孤,但是可能出現(xiàn),我們在使用的過程中不會用到這個div橱赠,這樣我們就會造成資源的浪費佛呻,dom的節(jié)點就會平白多出一個無用的div。

這時我們可以借助一個變量來判斷是否創(chuàng)建過div病线。代碼如下:

var mask;
function createMask() {
    if (mask) {
        return mask;
    } else {
        mask = $('<div/>').addClass('mask').appendTo($(document.body));
        return mask;
    }
}

細(xì)心的你是否發(fā)現(xiàn)這是一個單例吓著?

當(dāng)你在面試前對這個問題有研究,你說用一個單例模式來解決送挑,面試官會讓你先實現(xiàn)绑莺,然后讓你說說單例模式的理解,最后詢問相關(guān)的問題惕耕。如:什么是單例模式纺裁,單例模式有何優(yōu)缺點,如何使用單例模式司澎。

但是也有時候面試官會讓你直接使用一個設(shè)計模式來對它進(jìn)行優(yōu)化欺缘?

在這里,面試官的詢問方向跟面試官的知識面和掌控度有關(guān)挤安。所以谚殊,面試大廠或者面試中/高級工程師的童鞋還是把自己的所學(xué)知識技能系統(tǒng)化比較好。

你發(fā)現(xiàn)上面那段代碼實現(xiàn)有哪里不妥嗎蛤铜?對了嫩絮,你在函數(shù)體內(nèi)改變了函數(shù)外的變量mask的引用,在多人協(xié)作的項目中围肥,你寫的createMask是一個不安全的函數(shù)剿干,此外我們開發(fā)中應(yīng)盡量避免像mask這樣的全局變量使用,用一個局部變量如何來解決這個問題呢穆刻,我想很多同學(xué)會想到閉包置尔,修改后的代碼如下:

function createMask() {
    var mask;
    return function() {
        if (mask) {
            return mask;
        } else {
            mask = $('<div/>').addClass('mask').appendTo($(document.body));
            return mask;
        }
    }           
}

好吧,到了這里你可能在心里想‘這下總算完了吧’氢伟,是的榜轿,我想說的是這道題你答成這個樣子幽歼,對于中級工程師來說已經(jīng)過關(guān)了,但是對于高級工程師來說差导,你還需要對這個代碼進(jìn)行優(yōu)化试躏,如果經(jīng)常研究源碼的童鞋會見到這樣寫的代碼片段:

function createMask() {
    var mask;
    return function() {
        return mask || mask = $('<div/>').addClass('mask').appendTo($(document.body));  
    }           
}

對于那些開發(fā)框架,常用庫或插件的大牛來說设褐,同樣的功能颠蕴,同樣的性能,不會多浪費一個字符助析。

如果是面試高級工程師犀被,可能還會被問到,如何多個功能都要用到單例模式外冀,該如何解決寡键?

function singleton(fn) {
    var res;
    return function() {
        return res || (res = fn.apply(this, arguments))
    }
}

var createMask = singleton(function () {
    return $('<div/>').addClass('mask').appendTo($(document.body));
});

其實,這里又用到了另一種設(shè)計模式——橋接模式雪隧。

面試到這里一般就算完了西轩。通過上面的代碼我們發(fā)現(xiàn),設(shè)計模式也不是什么洪水猛獸脑沿,只不過是設(shè)計模式的使用靈活多變藕畔,但要想真正完全掌握設(shè)計模式,不是看兩篇文章就行的最重要的還是要多想庄拇,多實踐注服。

更多面試問題請關(guān)注我的github

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市措近,隨后出現(xiàn)的幾起案子溶弟,更是在濱河造成了極大的恐慌,老刑警劉巖瞭郑,帶你破解...
    沈念sama閱讀 206,839評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件辜御,死亡現(xiàn)場離奇詭異,居然都是意外死亡凰浮,警方通過查閱死者的電腦和手機我抠,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,543評論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來袜茧,“玉大人,你說我怎么就攤上這事瓣窄〉严茫” “怎么了?”我有些...
    開封第一講書人閱讀 153,116評論 0 344
  • 文/不壞的土叔 我叫張陵俺夕,是天一觀的道長裳凸。 經(jīng)常有香客問我贱鄙,道長,這世上最難降的妖魔是什么姨谷? 我笑而不...
    開封第一講書人閱讀 55,371評論 1 279
  • 正文 為了忘掉前任逗宁,我火速辦了婚禮,結(jié)果婚禮上梦湘,老公的妹妹穿的比我還像新娘瞎颗。我一直安慰自己,他們只是感情好捌议,可當(dāng)我...
    茶點故事閱讀 64,384評論 5 374
  • 文/花漫 我一把揭開白布哼拔。 她就那樣靜靜地躺著,像睡著了一般瓣颅。 火紅的嫁衣襯著肌膚如雪倦逐。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,111評論 1 285
  • 那天宫补,我揣著相機與錄音檬姥,去河邊找鬼。 笑死粉怕,一個胖子當(dāng)著我的面吹牛健民,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播斋荞,決...
    沈念sama閱讀 38,416評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼荞雏,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了平酿?” 一聲冷哼從身側(cè)響起凤优,我...
    開封第一講書人閱讀 37,053評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎蜈彼,沒想到半個月后筑辨,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,558評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡幸逆,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,007評論 2 325
  • 正文 我和宋清朗相戀三年棍辕,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片还绘。...
    茶點故事閱讀 38,117評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡楚昭,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出拍顷,到底是詐尸還是另有隱情抚太,我是刑警寧澤,帶...
    沈念sama閱讀 33,756評論 4 324
  • 正文 年R本政府宣布,位于F島的核電站尿贫,受9級特大地震影響电媳,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜庆亡,卻給世界環(huán)境...
    茶點故事閱讀 39,324評論 3 307
  • 文/蒙蒙 一匾乓、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧又谋,春花似錦拼缝、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,315評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至剩愧,卻和暖如春猪叙,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背仁卷。 一陣腳步聲響...
    開封第一講書人閱讀 31,539評論 1 262
  • 我被黑心中介騙來泰國打工穴翩, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人锦积。 一個月前我還...
    沈念sama閱讀 45,578評論 2 355
  • 正文 我出身青樓芒帕,卻偏偏與公主長得像,于是被迫代替她去往敵國和親丰介。 傳聞我的和親對象是個殘疾皇子背蟆,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,877評論 2 345

推薦閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 171,519評論 25 707
  • 工廠模式類似于現(xiàn)實生活中的工廠可以產(chǎn)生大量相似的商品,去做同樣的事情哮幢,實現(xiàn)同樣的效果;這時候需要使用工廠模式带膀。簡單...
    舟漁行舟閱讀 7,718評論 2 17
  • transform 功能:向元素應(yīng)用2D或3D轉(zhuǎn)換語法:transform:none|transform-func...
    別翹二郎腿閱讀 239評論 0 0
  • 昨天和媽媽和他一起去了中衛(wèi)的寺口子垛叨。在上山下山的路途中有了一絲絲的想法。 上山 上山的路途比較艱難 有一段特別陡的...
    暖陽洋的生活日記閱讀 280評論 0 1
  • clear all 清除所有變量 close all 關(guān)閉所有畫圖 clc 清屏 文件開頭上來先 clc clea...
    夕陽下的不回頭閱讀 223評論 0 0