方方-前端體系課程(四)

文章目錄

32.【算法與數據結構】僞代碼與流程圖

32.1 視頻:1

抽象能力: 越高級的程序員, 抽象能力越強

JS, Python, Java和PHP都有:

  • 聲明
  • if… else…
  • while, for循環
  • 函數
  • 對象

32.2視頻:2

  • 對編程的熱愛
  • 邏輯
    在這裏插入圖片描述
    在這裏插入圖片描述
    在這裏插入圖片描述
    推薦使用MIndjet畫流程圖

32.3 視頻:3

畫流程圖

32.4 視頻:4

在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
數據結構 = 數據形式 + 操作
在這裏插入圖片描述
用哈希表來解決該問題

33.【算法與數據結構】排序算法(上)

33.1 視頻:minOf2的實現

數據結構: 數組

找出較小的那個數

let minOf2 = ([a, b]) => a > b?a: b
//高手調用函數方法
minOf2.call(null, [1, 2])

這種寫法叫做析構賦值, 之後的課程會反覆使用.

現成min的JS的API

Math.min.call(null, 1, 2)
Math.min.apply(null, [1, 2])

@@@
Math看起來像Object一樣是構造函數, 實際上Math只是一個普通對象, 這是唯一的特例: 首字母大寫是構造函數.
@@細節@

33.2 視頻:minOf4的實現

在這裏插入圖片描述

33.3 視頻:min的實現

找出給出數組的最小值

let min = (numbers) =>{
	if(numbers.length > 2){
		return min([numbers[0], min(numbers.slice(1))])
	}else{
		return Math.min.apply(null, numbers)
	}	
}

在這裏插入圖片描述

33.4 視頻:實現sort排序

在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
任意長度的數組排序

let min = (numbers) =>{
	if(numbers.length > 2){
		return min([numbers[0], min(numbers.slice(1))])
	}else{
		return Math.min.apply(null, numbers)
	}	
}

let minIndex = (numbers) => numbers.indexOf(min(numbers))

let sort = (numbers) => {
	if(numbers.length > 2){
		let index = minIndex(numbers)
		let min = numbers[index]
		numbers.splice(index, 1)
		return [min].concat(sort(numbers))
	}else{
		return numbers[0]>numbers[1]? numbers.reverse(): numbers
	}
}

33.5 視頻:如何調試代碼

console大法:俗稱print大法

34.【算法與數據結構】排序算法(下)

34.1 視頻:選擇排序的循環寫法

let minIndex = numbers =>{
	let index = 0
	for(let i = 1; i< numbers.length; i++){
		if(numbers[index] > numbers[i]){
			index = i
		}	
	}
	return index
}

let swap = (array, i, j) => {
	let temp = array[i]
	array[i] = array[j]
	array[j] = temp
}

let selectSort = numbers =>{
	let index = 0
	for(let i = 0; i<numbers.length - 1; i++){
		//不改變原數組,即可找出逐漸遞減的數組中最小值的index
		index = minIndex(numbers.slice(i)) + i
		if(index !==i ){
			swap(numbers, index, i)
		}
	}	
	return numbers
}

@@@
所有遞歸都可以改成循環
@@細節@

34.2 視頻:快速排序

在這裏插入圖片描述

let quickSort = numbers => {
	if(numbers.length <= 1){
		return numbers
	}
	let pivotIndex = Math.floor(numbers.length / 2)
	let pivot = numbers.splice(pivotIndex, 1)[0]
	let left = []
	let right = []
	for(let i = 0; i< numbers.length; i++){
		if(numbers[i] < pivot){
			left.push(numbers[i])
		}else{
			right.push(numbers[i])
		}
	}
	return quickSort(left).concat([pivot], quickSort(right))
}

34.3 視頻:歸併排序

在這裏插入圖片描述

let merge = (a, b) => {
	if(a.length === 0) return b
	if(b.length === 0) return a
	return a[0] > b[0] ? [b[0]].concat(merge(a, b.slice(1))) : [a[0]].concat(merge(a.slice(1), b))
} 

let mergeSort = numbers => {
	let len = numbers.length
	if(len === 1){
		return  numbers
	}
	let left = numbers.slice(0, Math.floor(len/2))
	let right = numbers.slice(Math.floor(len/2))
	return merge(mergeSort(left),mergeSort(right))
}

34.4 視頻:計數排序

數據結構:哈希表(key:value這種類型)

let countSort = numbers => {
	let hashTable = {}, max = 0, result = []
	for(let i=0; i<numbers.length; i++){
		if(!(numbers[i] in hashTable)){
			if(numbers[i] > max){
				max = numbers[i]
			}
			hashTable[numbers[i]] = 1	
		}else{
			hashTable[numbers[i]] += 1
		}
	}
	for(let j=0; j<=max; j++){
		if(j in hashTable){
			for(let k=0; k<hashTable[j]; k++){
				result.push(j)
			}
		}
	}
	return result
}

34.5 視頻:四種排序的時間複雜度

在這裏插入圖片描述

34.6 視頻:其他的排序算法

35.【算法與數據結構】僞代碼與流程圖

35.1 視頻:隊列 & 棧

在這裏插入圖片描述

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>隊列</title>
    <link rel="stylesheet" href="./style.css">
</head>

<body>
    <div id="screen"></div>
    <div id="action">
        <button id="createNumber">取號</button>
        <button id="callNumber">叫號</button>
    </div>

    <div>
        當前號碼: <span id="newNumber"></span>
    </div>
    <div>
        當前隊列: <span id="queue"></span>
    </div>
    <script src="./main.js"></script>
</body>

</html>
#screen {
    border: 1px solid #000;
    width: 200px;
    height: 200px;
}
const divScreen = document.querySelector('#screen')
const btnCreateNumber = document.querySelector('#createNumber')
const btnCallNumber = document.querySelector('#callNumber')
const spanNewNumber = document.querySelector('#newNumber')
const spanQueue = document.querySelector('#queue')

let n = 0
let queueList = []
btnCreateNumber.onclick = () => {
    n += 1
    queueList.push.call(queueList, n)
    spanNewNumber.innerHTML = n;
    spanQueue.innerHTML = JSON.stringify(queueList);
    console.log(queueList)
}

btnCallNumber.onclick = () => {
    if (queueList.length == 0) {
        divScreen.innerHTML = ''
        return
    }
    const now = queueList.shift.call(queueList)
    divScreen.innerHTML = `請 ${now} 號, 取餐,祝您用餐愉快!`
    spanQueue.innerHTML = JSON.stringify(queueList);
}

在這裏插入圖片描述

35.2 視頻:鏈表

在這裏插入圖片描述

35.3 視頻:哈希表

哈希表
在這裏插入圖片描述

35.4 視頻:樹

在這裏插入圖片描述

36.【JS編程接口】DOM 編程

36.1 視頻:DOM(Document )介紹

DOM很難用, 所有後面纔會出現JQuery, Vue和React等

獲取元素, 也叫標籤:

  • window.idxxx或者會直接誒idxxx
  • document.getElementById('idxxx')
  • document.getElementsByTagName('div')[0]
  • document.getElementsByClassName('red')[0]
  • document.querySelector('#idxxx')
  • document.querySelector('.red')[0]

用哪一個: 工作中使用querySelector和querySelectorAll, 做demo直接使用idxxx(千萬別被人發現了), 要做兼容IE的可憐蟲才用getElement(s)ByXXX

36.2 視頻:獲取元素的API

獲取特定元素:

  • html元素
    document.documentElement
  • head元素
    document.head
  • body元素
    document.body
  • 窗口(窗口不是元素)
  • window
  • 所有蒜素
    document.all
    document.all是個奇葩, 第6個falsy值

36.3 視頻:元素的6層原型鏈

獲取的元素是對象:
在這裏插入圖片描述
div完整原型鏈:
在這裏插入圖片描述
節點(Node):
在這裏插入圖片描述

36.4 視頻:創建元素的API

1 創建一個標籤節點

let div1 = document.createElement('div')
document.createElement('style')
document.createElement('script')
document.createElement('li')

2 創建一個文本節點
text = document.createTextNode('你好')

3 標籤裏面插入文本

div1.appendChild(text1)
//法一(IE)
div1.innerText = '你好'
//法二(標準)
div1.textContent = '你好'
//不能用div1.appendChild('你好')

4 插入頁面中
創建的標籤默認處於JS線程中,必須把它插入到head(默認看不見)或者body中, 它纔會生效

document.body.appendChild(div)
已經在頁面中的元素.appendChild(div)
  • appendChild
let div = document.createElement('div')
test1.appendChild(div)
test2.appendChild(div)

@@@
最終div出現在test2中, 一個元素不能出現在兩個地方, 除非複製一份(let div2 = div1.cloneNode(true))
@@細節@

1 兩種方法

//舊方法
parentNode.removeChild(ChildNode)
//新方法(不兼容IE)
childNode.remove()

2 如果一個node被移除頁面(DOM樹), 那麼它還可以再次回到頁面中嗎?

div1.parentNode.removeChild(div1)
div1.remove()
document.body.appendChild(div1)

可以再次回到頁面, 刪除只是將node從頁面(DOM樹)移除, 回到了內存(線程)中, 當然可以再次回到頁面(DOM樹)中.


  • 1 寫標準屬性
//改calss
div.className = 'red'//全覆蓋
div.className += ' blue'//追加
div.calssList.add('red')//追加

//改style
div.style = ''//全覆蓋
div.style.屬性 = ''//修改對應屬性

//大小寫
//background-color
div.style.backgroundColor = 'black'
div.style['background-color'] = 'black'

//增加自定義屬性
div.setAttribute('data-x', 'text')
//改data-*屬性
div.dataset.x = 'frank'

2 讀標準屬性

//常規
div.style
div.className
div.id
//特殊
div.calssList
div.getAttribute('class')
a.href
a.getAttribute('href')

在這裏插入圖片描述

  • 改事件處理函數

1 div.onclick默認是爲null
默認點擊div不會有任何響應, 但是如果把div.onclick改爲一個函數fn, 那麼點擊div的時候, 瀏覽器就會調用這個函數, 並且是這樣調用的fn.call(div, event). div會被當做this, event則包含了點擊事件的所有信息, 如座標.
在這裏插入圖片描述
2 div.addEventListener
div.onclick升級版後面講

  • 改內容

1 改文本內容

div.innerText = 'xxx'
div.textContent = 'xxx'

2 改HTML內容(內容過長影響網站性能)

div.innerHTML = '<strong>重要內容<strong>'

3 改標籤

div.innerHTML = ''//先清空
div.appendChild(div2)//再添加內容
  • 改爸爸
newParent.appendChild(div)
div2.appendChild(div)

36.5 視頻:查看元素的API

1 查爸爸

node.parentNode
node.parentElement

2 查爺爺

node.parentNode.parentNode

3 查子代

node.childNodes 
node.children//推薦

node.childNodes, 如果有空格的話會算進去
在這裏插入圖片描述
想要正確表達子代個數, 第一種不能打空格用node.childNodes
在這裏插入圖片描述
第二種用node.children
在這裏插入圖片描述

  • 查看兄弟姐妹
node.parentNode.childNodes //還要排除自己(for循環)
node.parentNode.children //還要排除自己(for循環)

排除自己,實現代碼:

let sibling = []
let c2 = div.parentElement.children
for(let i=0; i< c2.length; i++){
	console.log(i)
	if(c2[i] !== div){
		sibling.push(c2[i])
	}
}
  • 查看老大
node.firstChild
  • 查看老幺
node.lastChild
  • 查看上一個哥哥/姐姐
node.previoussibling
  • 查看下一個弟弟/妹妹
node.nextSibling
  • 遍歷一個div裏面的所有元素
travel = (node, fn) => {
	fn(node)
	if(node.children){
		for(let i=0; i<node.children.length; i++){
			travel(node.children[i], fn)
		}
	}
}
travel(div1, (node)=> console.log(node))	

36.6 視頻:DOM操作跨線程

DOM操作是跨線程的

  • 瀏覽器功能分爲:渲染引擎JS引擎
    1 各線程各司其職
    JS引擎不能操作頁面, 只能操作JS. 渲染引擎不能操作JS, 只能操作頁面.
    那麼document.body.appendChild(div1), 是如何改變頁面的.

2 跨線程通訊
當瀏覽器發現JS在body裏面加了個div1對象, 瀏覽器就會通知渲染引擎在頁面裏也新增一個div元素, 新增的div元素所有屬性都照抄div1對象.
在這裏插入圖片描述

  • 插入新標籤完整過程
    1 在div1放入頁面之前
    對div1所有的操作都屬於JS線程內的操作

2 把div1放入頁面之時
瀏覽器會發現JS的意圖, 就會通知渲染線程在頁面中渲染div1對應的元素.

3 把div1放入頁面之後
對div1的操作都有可能會觸發重新渲染
div1.id = 'newId'可能會重新渲染, 也可能不會
div1.title = 'new'可能會重新渲染, 也可能不會
在這裏插入圖片描述
如果連續對div1多次操作, 瀏覽器可能會合併成一次操作, 也可能不會
合併了
在這裏插入圖片描述
加入test.clientWidth後, 不合並了.
在這裏插入圖片描述

  • 屬性同步
    1 標準屬性
    對div1的標準屬性的修改, 會被瀏覽器同步到頁面中, 比如id, className, title等
    2 data-*屬性
    同上
    3 非標準屬性
    對非標準屬性的修改, 則只會停留在JS線程中, 不會同步到頁面裏.
    在這裏插入圖片描述
    在這裏插入圖片描述
  • Property v.s. Attribute
    1 property屬性
    JS線程中div1的所有屬性, 叫做div1的property
    2 attribute也是屬性
    渲染引擎中div1對應標籤的屬性, 叫做attribute
    3 區別
    大部分時候, 同名的property和attribute值相等, 但是如果不是標準屬性, 那麼他們只會一開始時相等.同時注意attribute只支持字符串, 而property支持字符串, 布爾等類型.

36 測試

在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述

37.【JS編程接口】手寫 DOM 庫

37.1 視頻:什麼是封裝

  • 什麼是封裝

封裝: 通俗來說電腦筆記本就是CPU, 內存, 硬盤, 主板, 顯卡的封裝, 用戶只需要接觸顯示器, 鍵盤, 鼠標, 觸控板等設備即可操作複雜的計算機.

接口: 被封裝的東西需要暴露在一些功能給外部, 這些功能就是接口, 如USB接口, HDMI接口.設備只要支持這些接口, 即可與被封裝的東西通訊, 比如鍵盤, 鼠標支持USB接口, 顯示器支持HDMI接口
在這裏插入圖片描述
在這裏插入圖片描述

  • 術語

1 庫
我們把提供給其他人用的工具代碼叫做庫, 比如JQuery, Underscore

2 API
庫暴露出來的函數或屬性叫做API(應用程序接口 Application Programming Interface)

3 框架
當你的庫變得很大, 並且需要學習才能看懂, 那麼這個庫就叫做框架, 比如Vue/React

37.2 視頻:硬核寫DOM庫

  • 對象風格

1 也叫做命名空間風格
window.dom是我們提供的全局對象

2 增

window.dom = {
    //創建節點
    create(string) {
        const container = document.createElement("template")
        //trim(): 清除string左右兩邊空格
        container.innerHTML = string.trim()
        return container.content.firstChild
    },

    //新增弟弟
    //因爲沒有insertAfter(), 所以思路: 通過獲取最後的下一個插入之前, 相當於最後一個插入之後(如果沒有下一個節點, 那麼默認爲text或者null, 最終也能實現)
    after(node, node2) {
        node.parentNode.insertBefore(node2, node.nextSibling)
    },

    //新增哥哥
    before(node, node2) {
        node.parentNode.insertBefore(node2, node)
    },

    //新增兒子
    append(parent, node) {
        parent.appendChild(node)
    },

    //新增爸爸
    wrap(node, parent) {
        dom.before(node, parent)
        dom.append(parent, node)
    }


};

在這裏插入圖片描述
VScode打開設置快捷鍵: command+,
自動格式化代碼:
在這裏插入圖片描述
@@@

  • 爲啥test直接就是對應的id爲test的div
    因爲window.test是直接獲取id名爲test的方式, 可簡寫爲test.

  • 運行的before, after和append爲什麼只執行一次

@@問題@

3 刪除

    //刪除節點, 考慮到最新語法node.remove()會不兼容, 採用: 找到node父節點然後刪除其子節點, 並返回node
    remove(node) {
        node.parentNode.removeChild(node)
        //保留節點引用
        return node
    },

    //刪除後代(下一級)
    empty(node) {
        const array = []
        let x = node.firstChild
        while (x) {
            array.push(dom.remove(node.firstChild))
            x = node.firstChild
        }
        return array
    }

4 改

    //用於讀寫屬性
    //重載
    attr(node, name, value) {
        if (arguments.length === 3) {
            node.setAttribute(name, value)
        } else if (arguments.length === 2) {
            return node.getAttribute(name)
        }
    },

    //用於讀寫文本內容
    //適配
    text(node, string) {
        if (arguments.length === 2) {
            if ("innerText" in node) {
                //IE方式
                node.innerText = string
            } else {
                //firefox/chrome
                node.textContent = string
            }
        } else if (arguments.length === 1) {
            if ("innerText" in node) {
                //IE方式
                return node.innerText
            } else {
                //firefox/chrome
                return node.textContent
            }
        }
    },

    //用於讀寫HTML內容
    html(node, string) {
        if (arguments.length === 2) {
            node.innerHTML = string
        } else if (arguments.length === 1) {
            return node.innerHTML
        }
    },

    //用於修改style樣式
    style(node, name, value) {
        if (arguments.length === 3) {
            node.style[name] = value
        } else if (arguments.length === 2) {
            if (typeof name === 'string') {
                return node.style[name]
            } else if (name instanceof Object) {
                const object = name
                for (let key in object) {
                    node.style[key] = object[key]
                }
            }
        }
    },

    //class的添加/刪除
    class: {
        add(node, className) {
            node.classList.add(className)
        },

        remove(node, className) {
            node.classList.remove(className)
        },

        has(node, className) {
            return node.classList.contains(className)
        }
    },

    //添加數據監聽
    on(node, eventName, fn) {
        node.addEventListener(eventName, fn)
    },

    off(node, eventName, fn) {
        node.removeEventListener(eventName, fn)
    }

5 查

    //獲取單個/多個標籤
    find(selector, scope) {
        return (scope || document).querySelectorAll(selector)
    },

    //獲取父元素
    parent(node) {
        return node.parentNode
    },

    //獲取子元素
    children(node) {
        return node.children
    },

    //用於獲取兄弟姐妹元素
    siblings(node) {
        return Array.from(node.parentNode.children).filter(n => n !== node)
    },

    //獲取弟弟
    next(node) {
        let x = node.nextSibling
        while (x && x.nodeType === 3) {
            x = x.nextSibling
        }
        return x
    },

    //獲取哥哥
    previous(node) {
        let x = node.previousSibling
        while (x && x.nodeType === 3) {
            x = x.previousSibling
        }
        return x
    },

    //遍歷所有節點
    each(NodeList, fn) {
        for (let i = 0; i < NodeList.length; i++) {
            fn.call(null, NodeList[i])
        }
    },

    //獲取排名第幾
    index(node) {
        let list = dom.children(node.parentNode)
        let i
        for (i = 0; i < list.length; i++) {
            if (list[i] === node) {
                break
            }
        }
        return i
    }

37.3 視頻:總結

vscode打開多個窗口: ctrl+shift+n

38. 【JS編程接口】jQuery 中的設計模式(上)

38.1 創建項目

38.2 閉包 & 鏈式操作

38.3 實現find函數

  • jQuery是構造函數嗎?

1 是
因爲jQuery函數確實構造了一個對象

2 不是
因爲不需要寫new jQuery就能構造一個對象(以前講的構造函數都要結合new纔行)

3 結論
jQuery是一個不需要加new的構造函數
jQuery不是常規意義上的構造函數, 這是因爲jQuery用了一些技巧(目前沒必要講)

(口頭上)jQuery對象是指jQuery函數構造出來的對象, jQuery是一個函數.

在這裏插入圖片描述

38.4 $div.find返回新的api對象

定義const必須要賦值.

38.5 實現end函數

38.6 實現each/parent/ children

38 【JS編程接口】jQuery 中的設計模式(下)

39.1 window.$ = window.jQuery

多等號是從右向左執行

39.2 $div v.s. div

變量使用$開頭, 則表示該變量爲jQuery對象, 正常寫的話一般來說是DOM對象.

39.3 jQuery.prototype

原型的本意就是節約內存

JS中只有淺複製, 沒有深複製.

39.4 jQuery.prototype 續

  • 構造prototype:

1 變量問題
2 添加constructor

39.5 設計模式是什麼

在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述

39.【JS編程接口】DOM事件和事件委託

39.1 視頻:捕獲與冒泡

2002年, W3C發佈標準, 文檔名爲DOM Level 2 Events Specification, 規定瀏覽器應該同時支持兩種調用順序, 首先 爺爺->爸爸->兒子(由外到內找監聽函數, 叫事件捕獲), 然後按兒子->爸爸->爺爺(由內到外找監聽函數, 叫事件冒泡).有監聽函數就調用, 並提供時間信息, 沒有就跳過.

開發者自己選擇事件放在捕獲階段還是冒泡階段.
在這裏插入圖片描述

39.2 視頻:W3C事件模型

在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述

39.3 視頻:target, currentTarget, 取消冒泡

在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述

39.4 視頻:如何阻止滾動

在這裏插入圖片描述

39.5 視頻:自定義事件

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>JS Bin</title>
</head>
<body>
  <div id=div1>
    <button id=button1>點擊觸發 frank 事件     
    </button>
  </div>
</body>
</html>
button1.addEventListener('click', ()=>{
  //創建自定義時間frank
  const event = new CustomEvent("frank", {"detail":{name:'frank', age: 18}})
  button1.dispatchEvent(event)
})

button1.addEventListener('frank', (e)=>{
  console.log('frank')
  console.log(e)
})

39.6 視頻:事件委託

在這裏插入圖片描述

39.7 視頻:擴展內容(玄學)

在這裏插入圖片描述
在這裏插入圖片描述

40.【項目】前航項目介紹

41.【項目】前端導航站點-上

41.1 視頻:項目介紹

41.2 視頻:製作手機頁面

41.3 視頻:製作PC頁面

41.4 視頻:寫HTML和CSS

41.5 視頻:使用Icon

41.6 視頻:導入圖片

41.7 視頻:創建站點

  • 引入jQuery

1通過bootcdn, 選擇min.js的鏈接到index.html的main.js之前.

2 判斷是否引入成功jQuery

console.log($)
console.log(jQuery)
  • 尋找ul中的最後一個li標籤
//li.last失效, 改用li:last
const $lastLi = $siteList.find('li:last')

41.8 視頻:使用hashMap和localStorage

  • 爲什麼header和main等標籤都需要加class.

防止以後有人來寫該項目代碼的時候, 直接用header等標籤來添加樣式, 這樣會使得疊加了之間其他地方的樣式.

  • const hashMap = []

正常情況下會是一個全局變量, 因爲在parcel中所以就多了一層作用域使得hashMap不是全局變量, 在parcel中全局變量寫法window.hashMap

  • 清除除了最後一個li的所有li
// li:not(.last)失效, 改用li:not(:last)
$siteList.find('li:not(:last)').remove()
  • 勾選chrome瀏覽器中的Preserve log可以保留上個網站的console
    在這裏插入圖片描述
  • localStorage存儲數據

@@@
1 localStorage中的數據什麼情況下會消失
第一種情況(常見): 清除遊覽器的cookie
第二種情況:電腦的硬盤滿了, 然後chrome會智能刪除一些緩存文件.
第三種情況: chrome的無痕窗口模式
@@細節@

2 存儲數據
localStorage只接受string類型

//轉爲string
const string = JSON.stringify(hashMap)
//數據存入localStorage
localStorage.setItem('x', string)

3 獲取數據

//取localStorage數據
const x = localStorage.getItem('x')
//轉爲object
const xObject = JSON.parse(x)

42.【項目】前端導航站點(下)

42.1 視頻:定一個小目標

@@@
1 定一個目標, 實現它
2 沒有完美, 做到看不出bug
@@箴言@

42.2 視頻: 處理logo

處理英文字母變爲大寫:

  • js方法
    .toUpperCase()
  • css方法
    text-transform: uppercase;

42.3 視頻: 簡化URL

42.4 視頻: 刪除功能

42.5 視頻: PC網頁(媒體查詢)

42.6 視頻: PC網頁樣式優化

42.7 視頻: PC樣式影響了手機樣式

42.8 視頻: 鍵盤事件

42.9 視頻: 發佈到github

  • parcel build錯誤:
 /Users/bens/Documents/selfStudy/jiRenGu/fangFang-FrontEndSystem/41-FrontEndNavigationSite(1)/navigation/src/index.html: Error in parsing SVG: Unbound namespace prefix: "xlink"
Line: 0
Column: 66
Char: >

添加–no-minify

 parcel build src/index.html --no-minify

  • 調整parcel生成的index.html下的路徑

先查找命令

parcel build --help

然後找到命令
在這裏插入圖片描述
記得清空dist目錄後再執行命令

 parcel build src/index.html --no-minify --public-url ./

./可以用網站絕對路徑來替代

42.10視頻: yarn build 一鍵發佈

首先

yarn init -y

在文件package.json添加

{
  "scripts": {
    "build": "rm -rf dist && parcel build src/index.html --no-minify --public-url ./"
  },
  "devDependencies": {
    "cssnano": "^4.1.10"
  },
  "name": "navigation",
  "version": "1.0.0",
  "main": "index.js",
  "repository": "https://github.com/bens1320/Navigation.git",
  "author": "bens1320 <[email protected]>",
  "license": "MIT"
}

42.11 文章: 優秀的項目 = 用心的項目

很多同學認爲前航是一個小項目,不能放在簡歷裏。

這是一個錯誤的觀念。能不能放在簡歷裏完全取決你你有多用心。

比如有一個前端就把導航網頁做成了這樣:https://www.vipbic.com/rank.html

代碼很簡單,但是你就是能看出他的用心,不是麼?

當然我不是讓你也花費大量時間把前航做成他那樣,但是我喜歡你在做項目的時候能夠「用心」。

就說這些,自己體會一下~

43. 打console.log

44.【前後分離】AJAX 的原理

44.1 視頻:下載server.js

AJAX(Async JavaScript And XML): 用JS發送請求和接收響應.

  • AJAX是瀏覽器的功能(由微軟IE5推出)

原本是瀏覽器的功能(發請求和收響應), 後面瀏覽器開放出來, 在window上加了個XMLHttpRequest函數, 用這個構造函數(類)可以構造出一個對象, JS通過它實現發請求和收響應.

  • node-dev: 自動刷新代碼

安裝

yarn global add node-dev

44.2 視頻:複習server.js的用法

44.3 視頻:挑戰1 - 加載CSS

44.4 視頻:挑戰2 - 加載JS

44.5 視頻:挑戰3 - 加載HTML

動態加載html. 一般不用iframe了, 比較臃腫.用ajax來請求, 比較輕量.

44.6 視頻: onreadystatechange事件

專業的前端: 不會用onload和onerror(圖片, css, js等, 沒想到監聽ajax)事件( 因爲歷史原因:沒有很好匹配ajax,先發明這2個事件, 然後再發明的ajax, 因此報錯監聽不到404錯誤).

因此用onreadystatechange來替代上面2個事件函數.

44.7 視頻: 挑戰4 - 加載XML

DOM不僅僅可以操作HTML還可以操作XML.

44.8 視頻: 挑戰5 - 加載JSON

JSON(JavaScript Object Notation): 是一門語言, 它不是編程語言, 而是標記語言(HTML, XML, Markdown).

  • 支持的數據類型

string - 只支持雙引號, 不支持單引號和無引號
number - 支持科學計數法
bool - true和false
null - 沒有undefined
array
object - 比較常用

就只有6種, 注意跟JS的7種數據類型區別開來. 不支持函數, 也不支持變量(所以也不支持引用)

JSON是借鑑JS發明的.

  • JSON.parse

  • JSON.stringify

由於JS的數據類型比JSON多, 所以不一定能成功.

44.9 視頻: 加載分頁

44.10 視頻: 總結

45.【前後分離】異步與Promise

45.1 視頻:異步?回調?

在這裏插入圖片描述
打電話叫外賣是異步加回調.

回調是一個名詞.
在這裏插入圖片描述

回調: 寫了卻不用, 給別人調用的函數, 就是回調「回頭你調用一下唄」, 有將來的含義, 類似我回頭請你喫飯.
1 沒有調用f1
2 將f1傳給f2(別人)
傳的方式1(常見):

function f1 (){}
function f2 (){}
f2(f1)

傳的方式2:

f2.f1 = ()=>{}

例子: AJAX中

request.onreadystatechange = () => {}
//等價於
function onreadystatechange(){}
request.setCallback(onreadystatechange)

3 f2調用了f1

在這裏插入圖片描述

45.2 視頻:異步函數的例子

在這裏插入圖片描述
一個函數裏面可能有2個函數, 不要看見return認爲是該函數的return.
在這裏插入圖片描述
這樣得不到搖色子的返回值,需要用回調函數.
在這裏插入圖片描述
在這裏插入圖片描述
面試題:
在這裏插入圖片描述
在這裏插入圖片描述

45.3 視頻:Promise的用法

如果異步任務有兩個結果, 成功或失敗, 怎麼辦?
在這裏插入圖片描述
在這裏插入圖片描述
Promise/A+規範

析構賦值

const {success, fail} = options
//等價於
const success = options.success
const fail = options.fail

function縮寫有this, 箭頭函數沒有this

success(response){}
//等價於
success: function (response){}

以前用jQuery.ajax
然後.done是因爲前端promise規定沒制定之前, jQuery作者自己對比promise規範來自己設定的. 目前來看應該用.then

現在用axios
參考鏈接

45.4 視頻:總結

Promise不可以取消.
Axios發明canceltoken(編號)來終止ajax請求.來達到Promise可以取消的效果.
Promise是前端解決異步問題的統一方案.

46.【前後分離】跨域、CORS、JSONP

46.1 視頻:同源策略

跨域: 面試必必必問,菜逼必定不會答.
可用window.originlocation.origin可查看當前網站的源
同源策略是瀏覽器的功能: 不同源的頁面之間, 不準互相訪問數據. 目的是爲了保護用戶隱私.

referer不同. 可通過開發者工具查看.

46.2 視頻:創建兩個server.js

46.3 視頻:修改hosts

46.4 視頻:演示跨域被阻止

通過ajax訪問外網資源都會被阻止.

46.5 視頻:解決方法一:CORS

header中加入: Access-Control-Allow-Origin: 允許指定網站訪問

IE: 6 7 8 9 不支持CORS, 因此出現了JSONP

46.6 視頻:解決方法二:JSONP

在這裏插入圖片描述

callback是jsonp的函數名

46.7 視頻:referer和functionName

46.8 視頻:封裝JSONP

46.9 視頻:面試回答JSONP

46.10 視頻:跨域其他方案

47.【前後分離】靜態服務器

47.1 視頻:靜態服務器

多種類型轉換可以用hash表

47.2 視頻:處理錯誤

錯誤用try

47.3 視頻:問答

48【前後分離】Ajax 實戰:Cookie、Session

48.1 視頻:動態服務器是什麼

靜態服務器: 沒有請求數據庫, 就是靜態服務器.
動態服務器: 請求了數據庫, 就是動態服務器.

48.2 視頻:怎麼做用戶註冊

48.3 視頻:獲取post數據

48.4 視頻:使用cookie標記用戶

48.5 視頻:使用cookie記錄user id

cookie也可以前端設置, 但是不建議, 一般都是後端設置.

48.6 視頻:使用session會話保存用戶信息

防篡改user_id:
1 加密(JWT)
2 把信息隱藏在服務器(session) 一般用文件保存

48.6 視頻:session的時效性

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章