方方-前端体系课程(四)

文章目录

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 <yu1piao09@163.com>",
  "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的时效性

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值