第5章 JS-Web-API(上)
从基础知识到JSWebAPI
下面来进行一个抛砖引玉
回顾JS基础知识
1.变量类型和计算
2.原型和原型链
3.闭包和作用域
4.异步和单线程
5.其他(如日期、Math、各种常用API)
特点:表面看来并不能用于工作开中发代码
内置函数:Object Array Boolean String...
内置对象:Math JSON
我们连在页面弹出一句hello world都不能实现
JS基础知识:ECMA 262标准
JS-Web-API:W3C标准
那么JS-Web-API究竟做了些什么呢?
W3C标准中关于JS的规定有:
1.DOM操作
2.BOM操作
3.事件绑定
4.ajax请求
5.存储
JS-Web-API
没有规定任何JS基础相关的东西
不管什么变量类型、原型、作用域和异步
只管定义用于浏览器中JS操作页面的API和全局变量(window、document、navigator等等)
总结:
常说的JS(浏览器执行的JS)包含两部分:
JS基础知识(ECMA262标准)
JS-Web-API (W3C标准)
5-2 DOM本质
DOM(Document Oject Module)
题目
DOM是哪种基本的数据结构?
答:树
DOM操作的常用API有哪些?
答:
获取DOM节点,以及节点的property和attribute
获取父节点,获取子节点
新增节点,删除节点
DOM节点的attribute和property有什么区别?
property 只是一个JS对象属性的修改和获取
Attribute 是对html标签属性的修改和获取
5-3 DOM节点操作
获取DOM节点(有四种)
//第一种”元素“获取(getElementById)
var div1 = document.getElementById('div')
//第二种 集合获取(getElementsByTagName)
var divList = document.getElementsByTagName('div')
console.log(divList.length)
console.log(divList[0])
//第三种 集合获取(getElementsByClassName)
var containerList = document.getElementsByClassName('.container')
//第四种 集合获取(querySelectorAll)
var pList = document.queryAelectorAll('p')
property(属性,是DOM中 属性,是JavaScript里面的对象。例如:childNodes、firstChild)
var pList = document.querySelectAll('p')
var p = pList[0] //获取的js对象
console.log(p.style.width) //获取样式
p.style.width = '100px' //修改样式
console.log(p.className) //获取class
p.className = 'p1' //修改 class
//获取 nodeName 和 nodeType
console.log(p.nodeName)
console.log(p.nodeType)
Attribute(特性:是html标签的特性,他的值只能够是字符串。例如:id、class、title、align)
var pList = document.querySelectorAll('p')
var p = pList[0]
p.getAttribute('data-name')
p.setAttribute('data-name','color-red')
p.getAttribute('style')
p.setAttribute('style','font-size:12px')
5-4 DOM结构操作
1.新增节点
创建节点==》给创建的节点赋值==》让创建好的节点放到哪个节点下面
createElement('p') innerHTML appendChild
2.获取父节点parentElement
3.获取子节点childeNodes
4.删除节点 removeChild()
html Demo
<div id="div1">
<p id="p1">this is p1</p>
<p id="p2">this is p2</p>
</div>
<div id="div2">
<p id="p3">this is p3</p>
<p id="p4">this is p4</p>
</div>
1.新增节点
第一种是创建插入
var p = document.createElement('p')
p.innerHTML = 'new p'
var div1 = document.getElementById('div1')
div1.appendChild(p)
第二种是存在的移动到已有的后面
var p4 = document.getElementById('p4')
var div1 = document.getElementById('div1')
div1.appendChild(p4)
2.获取父节点
var p4 = document.getElementById('p4')
var div1 = document.getElementById('div1')
console.log(p4.parentElement) //<div id="div2">...</div>
console.log(div1.parentElement) //<body>...</body>
3.获取子节点
var div1 = document.getElementById('div1')
console.log(div1.childNodes)
console.log(div1.childNodes[0].nodeType) //text 3
console.log(div1.childNodes[1].nodeType) //p 1
console.log(div1.childNodes[0].nodeName) //text #text
console.log(div1.childNodes[1].nodeName) //p p
4.删除节点
var div1 = document.getElementById('div1')
var childNodes = div1.childNodes
div.removeChild(childNodes[1])
5-5 BOM操作
BOM(Browser Object Module)
题目
如何检测浏览器的类型
navigator
var ua navigator.userAgent
var isChrome = ua.indexOf('Chrome')
console.log(isChrome) //true则是chrome浏览器
screen
console.log(screen.width)
console.log(screen.height)
拆解url的各部分
location
location.href
location.protocol
location.host
location.pathname
location.search
location.hash
history
history.back()
history.forward()
第6章 JS-Web-API(下)
6-1 事件-知识点
题目
1.编写一个通用的事件监听函数
var btn = document.getElementById('btn1')
btn.addEventListener('click',function(event){
console.log('clicked')
})
function bindEvent(elem,type,fn){
elem.addEventListener(type,fn)
}
var a = document.getElementById('link')
bindEvent(a,'click',function(e){
e.preventDefault() //阻止默认行为
alert('clicked')
})
2.描述事件冒泡流程
//html 部分
<body>
<div id="div1">
<p id="p1">激活</p>
<p id="p2">取消</p>
</div>
</body>
//js 部分
var p1 = document.getElementById('p1')
var body = document.body
bindEvent(p1,'click',function(e){
e.stopPropatation() //阻止冒泡
alert('激活')
})
bindEvent(body,'click',function(e){
alert('取消')
})
代理
html 部分
<div id="div1">
<a href="#">a1</a>
<a href="#">a2</a>
<a href="#">a3</a>
...
</div>
js 部分
var div1 = document.getElementById('div1')
addEvent(div1,'click',function(e){
var target = e.target //获取当前点击元素
if(target.nodeName ==='A'){ //如果当前元素标签是a标签
alert(target.innerHTML)
}
})
完善通用绑定事件函数
function bindEvent(elem,type,selector,fn){
if(fn==null){
fn = selector
selector = null
}
elem.addEventListener(type, function(e){
var target
if(selector) {
target = e.target
if(target.matches(selector)){
fn.call(target,e)
}else{
fn(e)
}
}
})
}
//使用代理
var div1 = document.getElementById('div1')
bindEvent(div1,'click','a',function(e){
console.log(this.innerHTML)
})
//不使用代理
var a = document.getElementById('a1')
bindEvent(div1,'click',function(e){
console.log(a.innerHTML)
})
代理的好处
代码简洁
减少浏览器内存占用
3.对于一个无限下拉加载图片的页面,如何给每个图片绑定事件
答:采用2里面的代理就能实现
6-2 Ajax-XMLHttpRequst
题目
1.手动编写一个ajax,不依赖第三方库
知识点
XMLHttpRequest
var xhr = new XMLHttpRequest()
xhr.open("GET","/api",false)
xhr.onreadystatechange = function(){
if(xhr.readState == 4){
if(xhr.status == 200){
alert(xhr.responseText)
}
}
}
xhr.send(null)
状态码说明
//readyState
0-(未初始化) 还没有调用send方法
1-(载入) 已经调用send()方法,正在发生请求
2-(载入完成) send()方法执行完成,已经接收到全部响应内容
3-(交互) 正在解析响应内容
4-(完成) 响应内容解析完成,可以在客户端调用了
//status 状态码说明
2xx - 表示成功处理请求。 如 200
3xx - 需要重定向,浏览器直接跳转
4xx - 客户端请求错误,如404
5xx - 服务器端错误
2.跨域的几种实现方式
什么是跨域
浏览器有同源策略,不允许ajax访问其他域端口
跨域条件:协议、域名、端口,有一个不同就算跨域
http 80
https 443
可跨域的三个标签
<img src="http://www.baidu.com/images/1.jpg" />
<link href="" />
<script src="" ></script>
三个标签的场景
img用于打点统计,统计网站可能有其他域
link script 都可以使用CDN,CDN的也是其他域
<script> 可以用于JSONP
跨域注意事项
所有的跨域请求都必须经过信息提供方允许
如果未经允许即可获取,那是浏览器同源策略出现漏洞
JSONP实现原理
<script>
window.callback = function(data){
//这是跨域得到的信息
console.log(data)
}
</script>
<script src="http://www.baidu.com/api.js"></script>
//以上返回 callback({x:100,y:200})
服务器端设置http header
response.setHeader("Access-Control-Allow-Origin","http://a.com,http://b.com");
response.setHeader("Access-Control-Allow-Headers","x-Requested-With");
response.setHeader("Access-Control-Allow-Methods","POST,GET,PUT,DELETE,OPTIONS");
//接受跨域的cookie
response.setHeader("Access-Control-Allow-Credentials","true")
6-3 存储
题目:
描述一下cookie,sessionStorage,locationStorage的区别
容量
是否会携带到ajax中
API易用性
cookie
本身用于客户端和服务器端通讯
但是它有本地存储的功能,于是就被“借用”
使用document.cookie = ... 获取和修改即可
缺点
存储量太小,只有4kb
所有 http请求都带着,会影响获取资源的效率
API简单,需要封装才能使用 document.cookie = ...
localStorage和sessionStorage
html5朱门为存储而设计,最大容量5M
API简单易用
localStorage.setItem(key,value)
localStorage.getItem(key)
坑:
IOS safari 隐藏模式下
localStorage.getItem 会报错
建议:
统一使用try-catch封装
第7章 开发环境
7-1 开发环境介绍
IDE(写代码的效率)
webstorm
sublime
vscode
atom
插件 插件 插件!!!
7-2 Git
git(代码版本管理,多人写作开发)
正式项目都需要代码版本管理
大型项目需要多人协作开发
GIt和linux是一个作者
平时自己练习可以用下面两个
github、码云、码市等等
常用命令
git init //初始化.git
git add .
git checkout xxx //还原某个文件
git commit -m "xxx" //备注
git push origin master //推送到远程仓库
git pull origin master //从远程更新代码
git branch // 查看分支
git checkout -b xxx / git checkout xxx //创建且切到该分支 / 切到某分支
git merge xxx //合并某分支到该分支上
7-3 JS模块化
知识点
1.不适用模块化的情况
//util.js
function getFormateDate(date,type){
//type === 1 返回2017-06-15
//type === 2 返回2017年06月15日
//....
}
//a-util.js
function aGetFormatDate(date){
return getFormateDate(date)
}
//a.js
var dt = new Date()
console.log(aGetFormatDate(dt))
那我们页面上引用就需要
<script src="util.js"></script>
<script src="a-util.js"></script>
<script src="a.js"></script>
那么如果这样使用就暴露出来了几个弊端:
a.js顺序不能更改
b.使用代码中的函数必须是全局变量,才能暴露给对方使用,全局变量污染
c. a.js 知道引用a-util.js,但是它知道还需要依赖util.js吗?
2.使用模块化
针对上面的弊端我们有一个模块化的一个设想:
//util.js
export {
getFormateDate(date,type){
//type === 1 返回2017-06-15
//type === 2 返回2017年06月15日
//....
}
}
//a-util.js
var getFormateDate = require('util.js')
export {
aGetFormatDate(date){
return getFormateDate(date)
}
}
//a.js
var aGetFormatDate = require('a-util.js')
var dt = new Date()
console.log(aGetFormatDate(dt))
这样的话,自己需要的方法自己引入,使得依赖关系自动引入
函数和函数之间的调用,没有必要是全局变量,解决全局变量污染的问题
3.AMD
require.js
全局define函数
全局require函数
依赖JS会自动、异步加载
下面是require.js 实现方式:
//util.js
define(function(){
return {
getFormatDate: function(date,type){
if(type===1){
return '2018-06-12'
}
if(type === 2){
return '2018年06月12日'
}
}
}
})
//a-util.js
define(['util.js'],function(util){
return {
aGetFormatDate: function(date){
return util.getFormatDate(date,2)
}
}
})
//a.js
define(['a-util.js'],function(aUtil){
return {
printDate: function(date){
console.log(aUtil.aGetFormatDate(date))
}
}
})
//main.js
require(['a.js'], function(a){
var dt = new Date()
a.printDate(dt)
})
那页面怎么引用呢?
<script src="/require.min.js" data-main="./main.js"></script>
4.CommonJS
nodejs模块化规范,现在被前端大量采用,原因:
前端开发依赖的插件和库,都可以从npm中获取
构建工具的高度自动化,使得使用npm的成本非常低
CommonJS不会异步加载,而是同步一次性加载出来
5.AMD和CommonJS的使用场景
需要异步加载JS,使用AMD
使用了npm之后,建议只用CommonJS
## 7-4 打包工具
grunt
gulp
webpack
//webpack.config.js
const path = require('path');
const htmlWebpackPlugin = require('html-webpack-plugin');
const cleanWebpackPlugin = require('clean-webpack-plugin');
const webpack = require('webpack');
module.exports = {
mode: 'development',
devtool: 'cheap-module-eval-source-map', //production: cheap-module-source-map
// entry:'./index.js',
entry: {
main: './src/index.js',
// sub:'./index.js'
},
devServer: {
contentBase: './dist',
port: 8081,
open: true,
hot: true,
hotOnly: true
},
module: {
rules: [{
test: /\.(jpg|png|gif)$/,
use: {
loader: 'url-loader', //file-loader
options: {
//placeholder 占位符
name: '[path][name].[ext]',
outputPath: 'images/',
limit: 1000
}
}
}, {
test: /\.scss$/,
use: [
'style-loader',
// 'css-loader',
{
loader: 'css-loader',
options: {
importLoaders: 2,
// modules:true
}
},
'sass-loader',
'postcss-loader'
]
}, {
test: /\.css$/,
use: [
'style-loader',
'css-loader',
'postcss-loader'
]
}, {
test: /\.(eot|svg|ttf|woff|woff2)$/,
use: {
loader: 'file-loader'
}
}, {
test: /\.js$/,
exclude: /node_modules/,
loader: 'babel-loader',
//如果options配置的内容比较多,那么就可以把options的内容放入到.babelrc文件中
// options: {
// //下面注释的是针对babel/polyfill 来配置的
// // presets: [
// // ['@babel/preset-env', {
// // useBuiltIns: 'usage',
// // targets:{
// // chrome:'67' //只对大于chrome67这个版本上的进行补充,低于这个版本的话则不予处理,进而减小了打包文件的体积
// // }
// // }]
// // ]
// //下面这段针对的是plugin-transform-runtime 来配置的
// "plugins": [
// [
// "@babel/plugin-transform-runtime",
// {
// "corejs": 2,
// "helpers": true,
// "regenerator": true,
// "useESModules": false
// }
// ]
// ]
// }
}]
},
plugins: [
new htmlWebpackPlugin({
template: 'index.html'
}),
new cleanWebpackPlugin(['dist']),
new webpack.HotModuleReplacementPlugin()
],
output: {
// filename: 'bundle.js',
filename: '[name].js',
publicPath: '/',
path: path.resolve(__dirname, 'dist')
},
}
//package.json
{
"name": "webpack-demo",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"build": "webpack",
"watch": "webpack --watch",
"start": "webpack-dev-server",
"server": "node server.js"
},
"author": "",
"license": "ISC",
"devDependencies": {
"@babel/core": "^7.3.3",
"@babel/plugin-transform-runtime": "^7.2.0",
"@babel/preset-env": "^7.3.1",
"@babel/preset-react": "^7.0.0",
"autoprefixer": "^9.4.8",
"babel-loader": "^8.0.5",
"clean-webpack-plugin": "^1.0.1",
"css-loader": "^2.1.0",
"express": "^4.16.4",
"file-loader": "^3.0.1",
"html-webpack-plugin": "^3.2.0",
"node-sass": "^4.11.0",
"postcss-loader": "^3.0.0",
"sass-loader": "^7.1.0",
"style-loader": "^0.23.1",
"url-loader": "^1.1.2",
"webpack": "^4.29.5",
"webpack-cli": "^3.2.3",
"webpack-dev-middleware": "^3.6.0",
"webpack-dev-server": "^3.2.0"
},
"dependencies": {
"@babel/polyfill": "^7.2.5",
"@babel/runtime": "^7.3.1",
"@babel/runtime-corejs2": "^7.3.1",
"react": "^16.8.2",
"react-dom": "^16.8.2"
}
}
//postcss.config.js
module.exports = {
plugins: [
require('autoprefixer')
]
}
//.babelrc
{
"presets": [
["@babel/preset-env", {
"useBuiltIns": "usage",
"targets":{
"chrome":"67"
}
}],
"@babel/preset-react"
]
}
第8章 运行环境
8-1 页面加载 - 渲染过程
题目
从输入url到得到html的详细过程
1)加载的形式
输入url(或跳转页面)加载html(html)
加载html中的静态资源(img media font js css api)
2)加载的一个资源的过程
浏览器根据DNS服务器得到的域名的IP地址
向这个IP的机器发送http请求
服务器收到、处理并返回http请求
浏览器得到返回内容
3)浏览器渲染页面的过程
根据html生成DOM Tree
根据css 生成CSSOM
将DOM和CSSOM 整合形成 RenderTree
根据RenderTree开始渲染和展示
遇到<script>时,会执行并阻塞渲染
window.onload 和 DOMContentLoaded的区别
window.onload
页面全局资源加载完成后才执行,包括图片、视频
DOMContentLoad
渲染完即可执行,此时图片、视频可能还没有加载完
window.addEventListener('load',function(){
//
})
document.addEventListener('DOMContentLoad',function(){
//
})
8-2 性能优化
原则
多使用内存、缓存或者其他方法
减少CPU计算、减少网络请求
入手
加载页面和静态资源
页面渲染
优化
1.静态优化
静态资源的合并压缩
静态资源缓存
使用cdn让资源加载更快
使用SSR后端渲染,数据直接输出html中
2.渲染优化
css放在前面,js放在后面
懒加载(图片懒加载、下拉加载更多)
减少DOM查询,对DOM查询做缓存
减少DOM操作,多个操作尽量合并到一起执行
事件节流
尽早执行操作(如DOMContentLoaded)
8-3 安全性
1.XSS 跨站请求攻击
eg:
写博客,同时偷偷插入一段<script>
攻击代码中,获取cookie,发送自己的服务器
发布博客,有人查看博客内容
会把查看者的cookie发送到攻击者的服务器
预防:
前端替换关键字:
< 改为 <
改为 >
后端替换关键字
2.XSRF 跨站请求伪造
你已登录一个购物网站,正在浏览商品
该网站的付费接口:http://api.pay?id=100 但是没有任何验证
然后你收到一封邮件,隐藏着<img src=http://api.pay?id=100 >
你查看邮件的时候,你已经悄悄的付费购买了
解决方案:
增加验证流程,例如输入指纹、密码、短信验证码
8-3 面试技巧
1.简历
简介明了,重点突出项目经历和解决方案
把个人博客放在简历中,并且定期维护更新博客
把个人的开源项目放到简历中,并维护开源项目
简历千万不要造假,要保持能力和经历上的真实性
2.如何看到加班?
加班就像借钱,救急不救穷
千万不要挑战面试官,不要反考面试官
学会给面试官惊喜,但是不要太多
遇到不会的问题,说出你知道的也可以
谈谈你的缺点--- 说一下你最近在学习就可以了
网友评论