【答阿里寒冬面試題】呵呵,大神的面試題就是好!

前言

今天微博看到了寒冬大神的面試題,以爲挺有意思的,這裏就作一點解答javascript

談談你對CSS佈局的理解css

講講輸入完網址按下回車,到看到網頁這個過程當中發生了什麼。html

談談你對Web前端組件化的理解,Web Component會帶來怎樣的影響前端

談談你對前端資源下載性能優化的經驗和思考java

如今有不少的MV*框架,你對它們有什麼見解jquery

iOS體驗好在哪裏,Web能遇上麼?android

網頁遊戲怎麼作?ios

Hybrid技術應當如何應用?git

你最愛的前端框架是什麼,爲何?程序員

首先老師的題目都很大,很差答,我這裏技術有缺陷,答得很差你們不要噴我,能夠好好教育我嘛

淺談CSS佈局

概述

從網頁表現來看,HTML是實體自己,要實現各類優雅的佈局的須要依賴CSS
HTML元素兩大類型爲塊級元素與行內元素,網頁的佈局通常由塊級元素組織,元素不一樣便有不同的表現
要實現佈局就要用到與佈局有關的CSS屬性爲position,經常使用屬性爲static、absoulute、fixed、relative
position的做用是改變元素的狀態,由文檔流轉爲相對文檔流或者脫離文檔流元素(定位元素)
固然float也能引起塊級元素脫離文檔流,可是其表現與原理與上面不一致,並且要慎用float佈局
因而這裏便已經有三種「流」了,不一樣的佈局元素會處於不一樣的「執行環境」,在「執行環境」中才能方便的對其進行管理
這個管理的依據即是BFC(塊級做用域上下文),根據我粗淺的理解是,BFC也就是瀏覽器提供的一塊渲染區
文檔流的元素處於一個渲染區,而定位元素處於另外一層渲染區,float元素又會與之不一樣
各個渲染區中的元素具備其定位規則,最簡單的即是文檔流中的元素,遵循其塊級元素獨佔一行+盒模型的規則:
① 塊級元素獨佔一行,而且具備框(經典盒模型)
② 塊級元素間由margin屬性分割,而且垂直方向的margin會取其大者
③ 塊級元素一定左靠這父級塊級元素左邊框(包含塊,佈局上下文)
④ float元素不能影響塊級元素的BFC區域,可是其高度會參與計算
 
建立BFC的方式有:
① float
② overflow
③ display(使行內元素具備BFC)
④ position
 
基於此,咱們即可以實現咱們的佈局了,這裏以最簡單的兩列布局爲例(左邊導航,右邊內容主體)
因爲先出現的DOM先展現,因此內容優先原則,咱們會將主體dom先展現
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
  <title></title>
  <style>
    * { margin: 0; padding: 0; } div { border: 1px solid black; } #sidebar { position: absolute; left: 0; top: 0; width: 95px; } #content { margin-left: 100px; } </style> <script src="../jquery-1.7.1.js" type="text/javascript"></script> </head> <body> <div id="content"> 主體 </div> <div id="sidebar"> 導航 </div> </body> </html>
這裏從理論上說,即是觸發了siderbar元素的定位特性,其BFC與文檔流不相關了
固然,這裏siderbar可使用float實現,可是float自己應該用於處理文字與圖片包裹的需求,咱們本着職責分離的想法就別那樣幹了
並且使用float還會引發元素坍塌,這裏還要費勁去處理清除浮動

行內元素

行內元素的處理比較複雜,首先行內元素的高度由其line-height決定,因此不要妄想其設置一個行內元素的高度,這會引發意想不到的問題
舉一個例子來講,不少大型網站都會具備統計代碼,而此類統計代碼通常是以img作請求發出,這個時候可能會致使10px左右的白屏問題
這個就是妄想設置行內元素高度的結果,獨立的inline元素出現時,會爲其建立一個line boxes做爲容器(文字框)
一行文字一個line Boxes,一行高度由其中最高的行內元素肯定,上例中有一個height爲0的img,卻爲其生成了一個高度爲10的行高
下面的代碼中,div會被行內元素撐開,其高度會由span中line-height高者決定
<div>
  <span id="span1">主體 </span><span id="span2">導航 </span>
</div>

移動端的建議

① 移動端的文檔流渲染效率最高,應該避免大範圍使用定位元素,在小米,三星等低端下定位元素可能渲染不出來(解決方案是引發迴流)
② img元素加載失敗時候會有邊框,須要搞掉
③ 慎用fixed屬性,fixed對於移動端來講有點頭疼,首先會有文本聚焦fixed定位錯亂問題,其次在ios4的屏幕中,若是加上瀏覽器上下工具條,再用fixed可視區域會變得很小
④ ios是按塊渲染的,佈局時候能夠分塊,不會渲染可視區域外的內容
⑤ 動畫或者border-radius、box-shadow等屬性皆會使手機耗電加重(可是這個好像與咱們不要緊)
⑥ fixed元素爲其設置html可能不響應或者說渲染看不見,常見於ipod或者低端android
⑦ 固然能在佈局上用上一些語義化標籤天然是好事,這樣對SEO或者特殊人事有必定幫助,好比strong、article之類的

總結

由於我自己專一點在js對css瞭解較少只能作此解析,請儘可能拍磚指正

一次請求的完整流程

咱們一次網址輸入會發起一連串連鎖效應,可是由於我這邊對HTTP一塊不是十分熟悉,只能解釋本身瞭解的
一次URl輸入後,其流程以下,首先是請求響應的流程:
1 解析URL,解析域名生成惟一IP地址,開始搜索服務器
2 找到服務器後,服務器接收請求被服務器進程攔截;通常而言,.net的程序會被IIS處理,java會被jBoss或者tomcat處理
3 服務器處理請求,若是靜態文件的話直接返回,如果.net或者java等動態腳本會通過服務器編譯,執行其中的服務器端代碼
4 如果服務器端具備數據庫操做的話,這裏還須要與DB創建鏈接,操做數據庫
5 服務器處理結束後,生成最終的靜態HTML字符串返回,開始向請求者(客戶端)返回請求字符串,一次返回量過大就會分批次,這是一個優化點
6 服務器響應到達瀏覽器,瀏覽器開始處理請求,進入瀏覽器解析流程

請求返回後,便進入了咱們關注的前端模塊

簡單來講,瀏覽器會解析HTML生成DOM Tree,其次會根據CSS生成CSS Rule Tree,而javascript又能夠根據DOM API操做DOM
上面的文字描述的很簡單,事實上發生的事情,卻很複雜,這裏與代碼實現也頗有關聯,可是有幾個關鍵點:
頁面必定會等全部的HTML結構與CSS加載下來才渲染( webkit內核
好比咱們這裏使用fiddler限制其外鏈加載,咱們爲其限速爲10s
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
  <title></title>
  <style>
    div { border: 1px solid black; } a { color: Red; } </style> </head> <body> <div> <a id="span1" href="http://www.baidu.com">主體 </a><span id="span2">導航 </span> </div> <link href=" http://kb.cnblogs.com/style/common.css" rel="stylesheet" /> </body> </html>

咱們看到事實上62ms後頁面總體dom結構就加載好了,這個時候咱們是可使用js操做dom結構的,但這裏一個重點是:
CSS外鏈加載會阻塞js的執行,而且重置CSS會引發瀏覽器的迴流或者重繪,也就是:
css外鏈會阻塞整個頁面的渲染(顯示),可是其DOM結構是可操做的,中間若是有阻塞性的操做,好比alert的話會強制瀏覽器繪製頁面
上面的特性與css外鏈的順序無關,而且有幾個樣式相關的操做,便會執行幾回,最終採用最近或者優先級最高的樣式
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
  <title></title>
  <style>
    div { border: 1px solid black; } a { color: Red; } </style> </head> <body> <div> <a id="span1" href="http://www.baidu.com">主體 </a><span id="span2">導航 </span> </div> <script> document.getElementById('span2').innerHTML = '測試'; alert(1) </script> <script> alert(2) </script> <link href=" http://kb.cnblogs.com/style/common.css" rel="stylesheet" /> </body> </html>

一個須要注意的地方是, chrome與firefox或者IE表現不一致,firefox與IE都是先渲染頁面最後等段CSS下來後再次渲染
因此咱們不少同窗面試時說將css外鏈放到header中,而不是body中的理解都是隻知其一;不知其二,這裏真實的處理辦法是異步插入css外鏈才行
至少對於chrome須要作這個處理,不然頁面就是出不來,由於多數手機是webkit內核,保不齊這裏出多少事情
根據以上流程後,頁面也基本出來了,這裏簡述其流程
① 生成DOM樹
② 計算CSS樣式
③ 構建render Tree
④ reflow,定位元素位置與大小
⑤ 繪製頁面
上面過程若是js操做dom或者終結有一段style都會引發reflow,因爲img會在文檔加載結束後加載,可能會撐開頁面,致使迴流,因此通常須要對img設置尺寸
對於這塊的優化各位本身來吧,我這裏便只能理解到這個程度了
PS:事實上chrome得到請求時自己也有幾個事件點,這裏能夠用其開發性能插件,但對前端基本透明,咱們這裏不關注了

MVC與組件化

這裏我將2塊題目合到一塊兒了,我以爲這裏能夠連到一塊兒作說明

View分離

不少程序的變革集中積累在VIEW一塊的處理,緣由是這裏的需求是最複雜的,就View分離來講,最成功的我以爲是ASP到ASP.net的變革
最初的ASP程序,會將C#代碼寫在asp代碼中,這樣的結果即是頁面裏面既有html又有C#代碼,甚至一個js循環中會嵌套出C#的循環
PS:你必定要相信,那個時候不會有js分紅的概念,由於需求達不到
所謂的View分離即是,程序員確實受不了維護顯示與邏輯同時處於一個頁面的程序了,因而他選擇了改變,改變的結果即是拆分
View分離一大核心思惟即是, 分得開,合得攏,他們這裏引入一個codebehind方案將一個頁面文件分紅兩個(事實上是三個)

① index.apsx

② index.aspx.cs

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="index.aspx.cs" Inherits="_00綜合_11mvc_index" %>
public partial class _00綜合_10doc_write_index : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e) { } }

最終這兩個文件會和到一塊兒,兩個文件之間也可通訊,而通訊的橋樑是.net一個個被人詬病的組件,好比:

① button組件

② datalist

③ label組件

④ 偉大的gridview

各個組件在C#層面上會擁有一個ID進行約束,.cs文件即可以根據該ID爲其註冊各個事件,這個與javascript的模型便很是相似了

View分離的第一個優勢即是,用戶的界面變得乾淨了,不會有代碼混雜的現象,第二個優勢即是業務端的代碼能夠再分離,從而多了數據層、業務層等各個概念

而組件的出現讓.net變成了世界上開發最快的語言,這點誰也不能否認,而這些都是前端MVC出現或者組件出現的意義

前端View分離

與asp當初的狀況一致,js進行dom操做或者字符串拼接的目的事實上就是想造成一個可供展現的View,前端jser已經不再能忍受這種代碼了:

不少時候,咱們想將對應的模板單獨的放到一個地方,每次樣式如果有更改,只須要更改那個文件便可,只要與之呼應的「ID」不丟失便可,好比這樣的結構和代碼:

View Code
<div class="cui-pop-box">
  <div class="cui-hd">
      <%=title%> </div> <div class="cui-bd"> <div class="cui-error-tips"> <%=content%></div> <div class="cui-roller-btns"> <% for(var i = 0, len = btns.length; i < len; i++ ) {%> <div class="cui-flexbd <%=btns[i].className%>"> <%=btns[i].name%></div> <% } %> </div> </div> </div>

這樣作的道理是,這個樣子作到了表現與行爲分離,咱們分得開,而後回根據基類的一個機制,讓他們最終合到一塊,以完成功能

這裏咱們依舊須要強調一個前提:「ID」關聯不可丟失,不然「行爲」將不可表現,只要二者間關聯不丟,這裏即可輕鬆知足如下邏輯:

① CSS名修改(非標識性CSS名)

② 標籤改變

③ 描述性文字改變

......

MVC在前端

重構一書有說,重複性或者相似重複性的代碼應該抽象爲一個方法,程序員也不傻,在重複使用須要提示框需求後便會學會造成alert組件

組件的出現是代碼抽象,代碼重用的標識,這個樣子既能夠減小工做量也能夠減小代碼容量,而組件的實現與MVC思惟的很好詮釋

好比如下代碼:

View Code

事實上,MVC的任意一塊均可以做爲單獨的模塊實現,好比會有這樣的需求:一個model實例的變化會影響兩個View的顯示,可是僅僅對UI一塊來講咱們作了以下處理:

核心點變成了幾個屬性:

① template,根據他生成UI

② datamodel,根據他生成viewModel提供給template使用

③ eventArr,業務事件註冊點

這個代碼是Blade框架的UI基類,他是一個迷你MVC框架

 1     propertys: function () {
 2       //模板狀態
 3       this.template = ''; 4 this.datamodel = {}; 5 this.events = {}; 6 this.wrapper = $('body'); 7 this.id = _.uniqueId('ui-view-'); 8 9 //自定義事件 10 //此處須要注意mask 綁定事件先後問題,考慮scroll.radio插件類型的mask應用,考慮組件通訊 11 this.eventArr = {}; 12 13 //初始狀態爲實例化 14 this.status = 'init'; 15 16 // this.availableFn = function () { } 17 18 },

template做爲View的實現,datamodel做爲model實現,咱們會根據datamodel與template生成基本的view實體

這裏datamodel與template之間會有一個viewModel的映射關係,是爲了防止服務器端忽然將title變成Title而致使模板解析錯誤

而整個文件即是一個控制器,view有的事件行爲採用javascript委託技術所有註冊在根元素上,如此整個UI就活了,他的好處是:

① 具備繼承關係,能夠擁有統一的資源釋放,或者View通訊機制

② 代碼量也會減小

MVC與組件化的意義

MVC對前端的意義甚大,由於jser對MVC或者分模塊的思惟的深刻理解,咱們纔會將前端代碼作分離,這樣會有效的避免多人更改一個文件的難題

這對前端的推進做用不可謂不大!

組件化是對重複工做,重複代碼的下降,固然是好東西......

資源加載

前端優化的瓶頸始終在資源加載,只要加載快,不管你代碼寫的多慢(不要糾結死循環),都必定快,因此前端優化事實上一直都是一個主題:瘦身

壓縮

css sprite

延遲加載(主要針對圖片)

按需加載(主要針對首屏未用到的UI)

緩存

CDN

預加載

等詞語不斷的在前端出現,可是一個不可避免的事實是,需求愈加複雜,體驗要求越高,因此一個前端可能的事實是:

前端資源體積愈來愈大,避免此事發生不是前端說了算的,須要產品與交互一塊兒努力,清晰、體驗好、輕量級的設計誰不喜歡,可是廣告營銷也不能不考慮,總之此事路還長!

webapp的資源加載

對於webapp來講,首次加載的體積會更加大,由於其要求的庫更多,而且網速更慢,這個時候能夠採起fake頁的方案

咱們應該避免頁面長時間白頁,這個時候便提出了fake頁的概念。頁面渲染只須要完整的HTML以及CSS,這個即是第一個優化點。

從數據請求數以及請求量來講,webapp首頁的響應應該比較慢,如果任由js加載完成再渲染頁面,用戶頗有可能失去耐心。

可是從DOMContentLoaded來看,首頁事實上頁面響應比較迅速,因此這個加載結束後頁面第一屏便渲染結束,而後再異步加載js,當js改變後再動態改變dom結構中的一些關鍵點

這個時候一個靜態HTML頁面,裝載首屏的基本內容,讓首頁快速顯示

而後js加載結束後會立刻從新渲染整個頁面,這個樣子,用戶就能夠很快的看到頁面響應,給用戶一個快的錯覺,給人感受快得多。

是否按需加載

按需加載的話確實會對首屏加載有好處,可是是否按需加載卻不必定了,如下面兩個體驗爲例:

資源徹底加載

http://yexiaochai.github.io/blade/demo/dest.html

按需加載

http://yexiaochai.github.io/blade/demo/debug.html

PS:我這裏debug版本點擊時候未作mask處理,你們不要瘋狂點擊了

這裏各位直觀的感覺是什麼呢?是否是,首次加載後後續操做十分流暢,而按需加載的話,每次皆會感受有點「卡」

按需加載須要加載js和模板,這個過程天然卡,因此真正是否是要按需加載,或者多少資源按需加載有個臨界值,須要不斷的測試才行

最後,要減小資源的話,代碼的質量神馬的也須要考慮的,但對容量來講效用可能不是太大

IOS的體驗

IOS的體驗好,主要好在兩點:

① 清晰、簡潔、傻瓜化設計,連我媽均可以輕巧的操做蘋果手機其簡易型可想而知

② 用戶行爲模擬,IOS體驗第二點即是其無敵的動畫效果

如果說web應用想遇上(寒冬老師這裏遇上一詞用得十分貼切,他要說超過估計沒人理他了)native開發的話仍是有可能

可是若是說web應用要遇上IOS的設計的話,那麼還有無數荊棘須要踩過!而且有兩大前提:

① 網速快,用戶沒必要關心資源大

② 手機性能好,不說超越PC,至少能「遇上」PC吧

以上兩點成立的話,web應用遇上IOS體驗才變得可能,簡單來講就動畫而言,前端有哪些問題呢?

webapp中的動畫

webapp的一大優點即是在view切換時候能夠擁有媲美與native的動畫效果,可是不少時候那只是一種想法,真正的狀況卻不是這樣
產生此問題的緣由有:
① 手機CPU爛!
② 手機顯卡爛!就算四核其渲染也頗有問題
③ 高端手機瀏覽器會有BUG
④ 低端手機支持很差(國內山寨機笑而不語)
由於以上緣由,事實上作webapp的都會不一樣程度的弱化動畫,或者在局部區域使用動畫

難在何處?

dom樹過多
view的移動與簡單的圖片slider組件相差甚劇!緣由即是其dom結構可能很複雜,大dom樹的移動在移動端效果不好
就簡單列表頁來講,當項目超過100個時,使用IScroll類插件都應該很慎重,這類移動可能很是卡!
並且dom樹複雜度與業務直接相關,咱們沒有任何辦法去控制dom樹,由於業務代碼可能不會通過咱們的手,就算通過,你又確定本身作出來的dom樹有多小?不見得吧
長短頁問題
所謂長短頁即是一個view很長一個view很短,這裏問題處理十分討厭
首先咱們每次作切換須要將view位置切換至頭部(window.scroll(0, 0))如此的話ios中會引發
頁面viewport的變化(系統自動發生),或者會觸發低端工具欄的出現,這個時候頁面抖動無可避免
如果每次不執行window.scroll(0, 0),切換時候又會致使短的view不可見
我現階段想到的解決方案是,移動時候將scroll設得比較大,移動時候將bview的top值與scrollTop相同
最後仍然須要執行window.scroll(0, 0)的操做,因此,這個問題只能緩解,沒法解決
手機渲染問題
只要是作移動端的朋友,必定會對三星機或者一些低端機的渲染嗤之以鼻!
具體表現爲屢次操做style後,後面的操做瀏覽器不會搭理你
解決方案是:
① 引發瀏覽器強烈重繪
② 臨時增刪一個dom結構
可是涉及view切換動畫的話,頗有可能會出現一些莫名其妙的問題!

因此單單由簡單的webapp的切換都如此困難,web應用想遇上IOS的話還要等幾年......

Hybrid對前端的意義

應該說Ajax帶動了前端的首次革命,而移動端帶來了二次革命,而Hybrid將前端推上了風口浪尖!

原來我廠app是使用native開發的,會出現此等問題:一個應用須要養3個團隊(ios、android、winphone),並且一旦業務改變會讓開發抓狂!

而Hybrid的出現解決了此問題,一套前端代碼能夠用於四個地方:瀏覽器、ios、android、winphone,而這個倒是互聯網公司最須要的

最近兩年,移動大潮襲來,各個公司皆在搶佔移動端的份額,誰贏了這場戰鬥誰就是下一代王者,因此出現了一個事實:

市場的佔領、業務的擴展是第一位!

因此Hybrid的市場與需求比native大,可是這不是說native沒用了,由於更好的體驗咱們的追求,因此在Hybrid佔領市場結束後,可能須要改版爲native

除非那時前端的體驗能縮小與native的距離

Hybrid開發的問題

Hybrid提升了前端開發的門檻,由於Hybrid的調試難,可是業內也出現了一些調試的方案,我這裏有一套Hybrid調試的技巧,有興趣能夠交流

Hybrid 兼容BUG多,總所周知,H5站點上看着好好的程序,一旦到了webview上就出問題了,這個調試也很痛苦

哎,其實Hybrid開發也只是須要一點熟悉度罷了,沒有什麼可說的,就此打住吧

結語

寒冬老師喜歡出題,我喜歡答題,其中幾道題我這裏沒有什麼概念就交白卷了,不知道個人回答是否能夠及格

如果寒冬老師或者各位以爲個人回答能勉強及格,左邊微博求粉!!!尼瑪我粉絲太少了!!!

相關文章
相關標籤/搜索