一個頁面從加載到完成,首先生成DOM樹,而後根據DOM節點的幾何屬性生成render樹(渲染樹),當渲染樹構建完成,頁面開始根據DOM樹佈局,渲染樹也會根據設置的樣式渲染節點javascript
迴流: 當咱們刪除或修改元素高度時,頁面會從新佈局,DOM樹發生變化,引發渲染樹從新渲染,這個過程叫作迴流(迴流必定形成重繪)css
重繪: 當修改元素的顏色,渲染樹會根據新規則從新渲染,這個過程叫作重繪(重繪不必定形成迴流)html
如何減小回流前端
function addDivs(element) {
var div;
// Creates a new empty DocumentFragment.
var fragment = document.createDocumentFragment();
for (var i = 0; i < 20; i ++) {
div = document.createElement('a');
div.innerHTML = 'Heya!';
fragment.appendChild(div);
}
element.appendChild(fragment);
}
複製代碼
------ html-------
<ul>
<li>Coffee</li>
<li>Milk</li>
<li>Soda</li>
</ul>
複製代碼
let lis = document.getElementsByTagName('li')
for (let i=0; i<lis.length; i++) {
lis[i].index = i
}
document.getElementsByTagName('ul')[0].addEventListener('click', handle, false)
function handle (event) {
if (event.target.tagName === 'LI') {
console.log(event.target.index)
}
}
複製代碼
$('li').click(function () {
console.log($(this).index())
})
複製代碼
點我ԅ(¯﹃¯ԅ)vue
fixed、relative、absolutejava
相對定位和固定定位,都會使塊級元素產生BFC,下面經過步驟檢測一下node
設置父元素爲固定定位,不設置高度,內部box設置高度和寬度,根據BFC內部box垂直排列的特徵,效果以下jquery
<div class="sj">
<div>1</div>
</div>
複製代碼
.sj{
position: fixed;
top: 0;
left: 0;
width: 200px;
background-color: #ccc;
}
.sj>div{
height: 20px;
width: 100px;
background-color: #2db7f5;
}
複製代碼
.sj>div{
height: 20px;
width: 100px;
position: absolute;
background-color: #2db7f5;
}
複製代碼
僞類:向某些選擇器設置特殊效果,用於選擇器選擇不到的元素webpack
僞元素:向某些選擇器添加特殊效果web
BFC是一個獨立的塊級渲染容器,擁有本身的渲染規則,不受外部影響,不影響外部
特徵
產生條件
做用
1. 父元素設置僞類:clear:both + zoom:1
設置zomm爲了兼容IE
<div class="parent1 clearFloat">
<div class="left"></div>
</div>
<div class="parent2"></div>
.parent1{
border: 1px solid red;
}
.parent2{
height: 100px;
border: 1px solid blue;
}
.left{
width: 200px;
height: 200px;
background-color: #5cadff;
float: left;
}
.clearfloat::after{
display: block;
clear: both;
content: '';
visibility: hidden;
height: 0;
}
.clearfloat {
zoom: 1
}
複製代碼
2. 結尾處添加空白標籤:claer:both
<div class="parent1">
<div class="left"></div>
<div class="clearfloat"></div>
</div>
<div class="parent2"></div>
.clearfloat{
clear: both;
}
複製代碼
3. 父元素產生BFC
BFC內浮動元素高度計算在內
方法1、定位 + transform
.parent{
height: 500px;
width: 500px;
border: 1px solid red;
position: relative;
}
.child{
height: 80px;
width: 80px;
background-color: #515A6E;
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
}
複製代碼
方法2、margin + transform
.parent{
height: 500px;
width: 500px;
border: 1px solid red;
}
.child{
height: 80px;
width: 80px;
background-color: #515A6E;
margin: 50% 0 0 50%;
transform: translate(-50%, -50%);
}
複製代碼
方法3、定位 + 負margin
.parent{
height: 500px;
width: 500px;
border: 1px solid red;
position: relative;
}
.child{
height: 80px;
width: 80px;
background-color: #515A6E;
position: absolute;
top: 50%;
left: 50%;
margin: -40px 0 0 -40px;
}
複製代碼
方法4、flex
.parent{
height: 500px;
width: 500px;
border: 1px solid red;
display: flex;
align-items: center;
justify-content: center;
}
.child{
height: 80px;
width: 80px;
background-color: #515A6E;
}
複製代碼
方法5、table-cell
.parent{
height: 500px;
width: 500px;
border: 1px solid red;
display: table-cell;
text-align: center;
vertical-align: middle;
}
.child{
display: inline-block;
height: 80px;
width: 80px;
background-color: #515A6E;
}
複製代碼
標準盒子模型
width = content
IE盒子模型
width = border + padding + content
塊級元素
行內元素
行內置換元素
瀏覽器依據元素的標籤和屬性來決定元素的具體顯示內容
img、input、textarea、select、object屬於行內置換元素, 具備塊級元素的特徵(除寬度外)
元素脫離文檔流,但由於沒有設置屬性致使沒法具體定位,緊跟在上個元素以後,但下個元素排列時會忽略此元素
<div id="a">
<span class="b">222</span> // 紅色
</div>
div span{
color: blue;
}
#a {
color: red;
}
複製代碼
!important(10000) > 內聯樣式(1000) > id(100) > class|僞類|屬性選擇(10) > 標籤|僞元素(1) > 通配符(0) > 繼承(無)
假設只走一個臺階,有1種走法;兩個臺階,2中走法,三個臺階,3種走法;四個臺階,5種走法...
1->1; 2->2; 3->3; 4->5...能夠看出此問題是斐波那契數列,即下個值是前兩個值的和
公式爲:f(n) = f(n-1) + f(n-2)
方法1、遍歷相加
function test (num) {
let num1 = 1, num2 = 2, res = 0
for (let i=2; i<num; i++) {
res = num1 + num2
num1 = num2
num2 = res
}
return res
}
複製代碼
方法2、遞歸 (不推薦)
function test (num) {
if (num === 1)
return 1
else if (num === 2)
return 2
else
return test(num-1) + test(num-2)
}
複製代碼
閉包
使用場景
function Cat(){}
Cat.prototype = new Animal();
Cat.prototype.name = 'cat';
// Test Code
var cat = new Cat();
複製代碼
function Cat(name){
Animal.call(this)
this.name = name || 'Tom';
}
var cat = new Cat()
複製代碼
let newArr = JSON.Parse(JSON.Stringify(oldArr))
複製代碼
擴展運算符
<!-- 僅對包含基本數據類型的數組有效 -->
let newArr = [...oldArr]
複製代碼
function deepClone (obj) {
let newObj = obj instanceof Array ? [] : {}
for(var i in obj){
newObj[i] = typeof obj[i] == 'object' ? deepClone(obj[i]) : obj[i]
}
return newObj
}
複製代碼
function test (num) {
let arr1 = [], arr2 = [],arr = [] // arr1保存小數前, arr2保存小數後
arr = num.toString().split('.')
arr2 = arr[1] ? [...arr[1]] : [] // 判斷是否存在小數,並將每項轉爲數組元素
arr1 = [...arr[0]]
let newArr1 = arr1.map((item, index) => arr1.length === (index+1) && (index+1)%3 === 0 ? item : (index+1)%3 === 0 ? item+',' : item)
let newArr2 = arr2.map((item, index) => arr2.length === (index+1) && (index+1)%3 === 0 ? item : (index+1)%3 === 0 ? item+',' : item) // 數組爲空則map()不檢測
newArr2.unshift('.')
console.log(newArr1.concat(newArr2).join(''))
}
test(123456789.123)
複製代碼
快速排序採用分治法的思想,將一個複雜問題分爲兩個或多個子問題,直到子問題簡單到能夠直接求解,那麼子問題的解的組合即是原問題的解
function quickSort (arr) {
if (arr.length <= 1) return arr;
//取中間位置的數據做爲基準值,並從原數組中刪除該基準值
let jzIndex = Math.floor(arr.length/2) // 獲取基準值下標
let jzNum = arr.splice(jzIndex, 1) // 刪除並獲取基準值
let leftArr = [], rightArr = [] // 分別保存小於和大於基準值的數據
arr.forEach(item => {
if (item < jzNum[0]) {
leftArr.push(item)
}
if (item >= jzNum[0]) {
rightArr.push(item)
}
})
//concat()鏈接兩個數組
return quickSort(leftArr).concat(jzNum, quickSort(rightArr))
}
console.log(quickSort([10,5,15,2,4]))
複製代碼
防抖: 任務頻繁觸發狀況下,只有兩次任務間隔超過指定時間,纔會執行。若還未超過卻又一次觸發,則時間從新開始計算
// 防抖函數
function debounce (fn, time) {
// 新建一個變量保存定時器
let timeout = null;
return function () {
// 每次用戶點擊、輸入時,清空上一個定時器
clearTimeout(timeout)
timeout = setTimeout(() => {
fn.call(this, arguments)
}, time)
}
}
// 處理函數
function handler () {
console.log('防抖成功!')
}
// 觸發
debounce(handler, 1000)
複製代碼
節流: 頻繁觸發任務,任務按照必定時間間隔進行執行
// 節流函數
function throttle (fn, time) {
// 利用閉包保存是否可執行的變量
let canRun = true
return function () {
// 若是爲false,則終止函數執行
if (!canRun) return;
// 執行前將變量設爲false
canRun = false
setTimeout(() => {
fn.call(this, arguments)
canRun = true
}, time)
}
}
// 處理函數
function handler () {
console.log('節流成功!')
}
// 觸發
throttle(throttle, 1000)
複製代碼
1. 什麼是Promise?
2. Promise優缺點?
優勢:
缺點:
3. Promise的方法有哪些?做用都是什麼?
Promise.prototype.then()
Promise 實例添加狀態改變時的回調函數,then方法的第一個參數是resolved狀態的回調函數,第二個參數(可選)是rejected狀態的回調函數
then方法返回的是一個新的Promise實例(注意,不是原來那個Promise實例)。所以能夠採用鏈式寫法,即then方法後面再調用另外一個then方法。
Promise.prototype.catch()
.then(null, rejection)或.then(undefined, rejection)的別名,用於指定發生錯誤時的回調函數。
Promise.prototype.finally()
不管Promise最後狀態如何,都會執行finally內的函數,ES2018引入
Promise.all()
多個Promise同時執行,若所有成功,則以數組形式返回執行結果;如有一個是rejected,則只返回rejected的結果
Promise.race()
多個Promise同時執行,返回最早結束Promise執行任務的結果,不管成功或失敗
Promise.resolve()
返回一個新的 Promise 實例,該實例的狀態爲resolve
Promise.reject()
返回一個新的 Promise 實例,該實例的狀態爲rejected
4. promise如何使用?
5. 手寫一個promise
// 定義Promise構造函數
function Promise (exector) {
let self = this;
this.value = undefined;
this.reason = undefined;
// 定義Promise的狀態
this.status = 'pending'
// 存儲then中成功的回調函數
this.onResolvedCallbacks = [];
// 存儲then中失敗的回調函數
this.onRejectedCallbacks = [];
function resolve (value) {
if (self.status === 'pending') {
self.value = value
self.status = 'resolved'
self.onResolvedCallbacks.forEach(fn => fn())
}
}
function reject (reason) {
if (self.status === 'pending') {
self.reason = reason
self.status = 'rejected'
self.onRejectedCallbacks.forEach(fn => fn())
}
}
// 異常處理
try{
exector(resolve, reject)
}catch (e) {
reject(e)
}
}
// 在Promise原型上定義then方法,參數爲成功和失敗的回調
Promise.prototype.then = function (onFulfilled, onRejected) {
let self = this;
if (this.status === 'resolved') {
onFulfilled(self.value)
}
if (this.status === 'rejected') {
onRejected(self.reason);
}
if (this.status === 'pending') {
this.onResolvedCallbacks.push(() => {
onFulfilled(self.value)
})
this.onRejectedCallbacks.push(() => {
onRejected(self.reason)
})
}
}
let promise = new Promise((resolve, reject)=> {
setTimeout(() => {
resolve('success')
}, 1000)
})
promise.then(data => {
console.log(data)
}, err => {
console.log(err)
})
複製代碼
webpack是模塊打包工具,對js模塊和擴展語言進行打包供瀏覽器識別運行
Grunt和Gulp屬於任務流工具Tast Runner
webpack屬於模塊打包工具 Bundler
方法1、經過父組件通訊
此方法須要保證兄弟組件A、B都在同一個父組件下;
父組件經過接受子組件A傳遞過來的事件消息,並調用子組件B
子組件A
this.$emit('transmit', 'msg')
複製代碼
父組件
<ChildA @transmit="transmit"></ChildA>
<ChildB :msg="msg"></ChildB>
transmit (data) => {
this.msg = data
}
複製代碼
子組件B、須要使用watch來監聽父組件props穿過來的數據變化
watch (new, old) {
數據操做...
}
複製代碼
方法2、eventBus
經過建立Bus.js註冊一個全局實例,通信組件經過調用實例的方法達到通信目的
// eventBus 共享vue實例,用於兄弟組件數據傳遞
import Vue from 'vue'
const Bus = new Vue({})
export {Bus}
複製代碼
import {Bus} from './Bus.js'
Bus.$emit('transmit', 'msg')
複製代碼
import {Bus} from './Bus.js'
mounted () {
Bus.$on('transmit', (data) => {
操做...
})
}
因爲$on事件沒法主動銷燬,因此須要根據業務手動進行銷燬
在組件銷燬前方法中銷燬
beforeDestory () {
Bus.$off('transmit')
}
或者在使用前進行銷燬
mounted () {
Bus.$off('transmit')
Bus.$on('transmit', (data) => {
操做...
})
}
複製代碼
Vue Router 是路由管理器,能夠改變url而不向服務器發送請求,頁面無需刷新
有hash和history兩種路由模式
hash模式
history模式
動態路由匹配中會複用同一組件,這就致使再次訪問組件不被從新渲染,聲明週期鉤子不會執行,這就須要咱們用watch去監聽路由的變化
watch: {
$route(to, from) {
······
}
}
複製代碼
Vuex 是一個專爲 Vue.js 應用程序開發的狀態管理模式
Vuex包含五個屬性:state、getter、mutation、action、module
當組件進行數據修改的時候,經過調用dispatch來觸發actions裏面的方法,actions裏每一個方法都有commit方法,經過執行commit方法來觸發mutation裏的方法進行數據修改,因爲mutation裏每一個函數都有一個state參數,進而可對state進行修改,當數據修改完畢後,會傳導給頁面。頁面的數據也會發生改變。
watch用來監聽並響應數據的變化
data () {
return {
age: 20,
obj: {
age: 24
},
arr: [1,2,3]
}
}
複製代碼
1. 監聽基本類型
watch: {
age (newd, oldd) {
...
}
}
複製代碼
2. 監聽對象
watch: {
obj: {
handler (newd, oldd) {
...
},
deep: true, // 開啓深度監聽
immediate: true // 首次即執行
}
}
複製代碼
3. 監聽對象某個屬性
*** 採用字符串
watch: {
'obj.age': {
handler (newd, oldd) {
...
}
}
}
*** 利用computed計算屬性
computed: {
age () {
return this.obj.age
}
}
watch: {
age (newd, oldd) {
...
}
// 也可寫爲
age: {
handler (newd, oldd) {
...
}
}
}
複製代碼
異步更新隊列
Vue 異步執行 DOM 更新。只要觀察到數據變化,Vue將開啓一個隊列,並緩衝在同一事件循環中發生的全部數據改變。若是同一個 watcher被屢次觸發,只會被推入到隊列中一次。這種在緩衝時去除重複數據對於避免沒必要要的計算和 DOM 操做是很是重要的。而後,在下一個的事件循環「tick」中,Vue刷新隊列並執行實際 (已去重的) 工做。Vue 在內部嘗試對異步隊列使用原生的Promise.then和MessageChannel,若是執行環境不支持,會採用 setTimeout(fn, 0) 代替。
例如,當你設置 vm.someData='newvalue',該組件不會當即從新渲染。當刷新隊列時,組件會在事件循環隊列清空時的下一個「tick」更新
nextTick
因爲DOM是異步執行更新的,有時咱們修改完數據等待DOM更新後進行操做,則此刻可以使用Vue.nextTick(callback)
Vue.component('example', {
template: '<span>{{ message }}</span>',
data: function () {
return {
message: '沒有更新'
}
},
methods: {
updateMessage: function () {
this.message = '更新完成'
console.log(this.$el.textContent) // => '沒有更新'
this.$nextTick(function () {
console.log(this.$el.textContent) // => '更新完成'
})
}
}
})
複製代碼
由於 $nextTick() 返回一個 Promise 對象,因此你可使用新的ES2016async/await語法完成相同的事情:
methods: {
updateMessage: async function () {
this.message = 'updated'
console.log(this.$el.textContent) // => '未更新'
await this.$nextTick()
console.log(this.$el.textContent) // => '已更新'
}
}
複製代碼
客戶端 ->(創建鏈接)-> 服務器
客戶端 <-(確認接受,創建鏈接)<- 服務器
客戶端 ->(確認接受)-> 服務器
複製代碼
客戶端 ->(關閉鏈接)-> 服務器
客戶端 <-(確認關閉)<- 服務器
客戶端 <-(關閉鏈接)<- 服務器
客戶端 ->(確認關閉)-> 服務器
複製代碼
2XX 請求成功
3XX 重定向
4XX 客戶端錯誤
5XX 服務器錯誤
XSS(跨站腳本攻擊)是在網頁中注入非法的js腳本,獲取cookie達到控制瀏覽器的目的
危害:
防範方法:
CSRF 跨站點請求僞造,冒充用戶發起請求,完成一些違背用戶意願的事情(如修改用戶信息等)
危害:
防範方法:
token使用原理
同源策略: 具備相同的協議(http/https)、域名、端口即爲同源,不存在跨域,反之亦然
跨域資源共享(CORS)
需後端設置
服務器轉發代理
請求同源地址的代理接口,服務器訪問跨域接口並返回數據
jsonp
利用script標籤不受同源策略限制的特徵,在src內寫入請求地址,末尾回調處理數據
<script type="text/javascript" src="http://localhost/Service.ashx?callback=jsonpCallback" />
複製代碼
cookie
sessionStorage
localStorage
圖片大體分爲png、jpg、gif三種
優化方案:
當加載圖片過大時,會出現局部逐步加載狀況,用戶體驗差;可經過喲圖片的onload方法來判斷圖片是否加載完成,未加載完前先display:none;進行隱藏,當onload後在進行加載。
假設桌子小到只能放下一枚硬幣,那麼先放者贏;若不肯定桌子大小,則首先在圓心處放硬幣,而後在對手放完後的關於圓心的對稱點處再放硬幣,確保先放者贏