学习目标
了解为何进行前端页面的优化
了解SEO,掌握前端页面语义性的评判标准与规则
从代码可读性角度进行页面优化
学习目标
- 掌握前后台的数据传递时存在的问题
- 合理处理文本或图片的超出问题
- 灵活应用margin负值、伪类选择器等技术,解决代码的扩展性问题
- 掌握伪元素并能够合理应用
- 理解a标签的可触区,并能够合理设置
前后台数据交互的常见问题
图片尺寸与文本溢出
为合理处理“相似元素的不同样式”
img标签的宽高与文本超出
图片、文本问题处理方法
为图片设置合理的宽高
文本超出隐藏
overflow: hidden;
文本超出省略号
overflow: hidden;
text-overflow: ellipsis;
word-break: keep-all;
white-space: nowrap;
代码的扩展性 — 伪类选择器
代码扩展性 — margin的负值
伪元素的应用
a标签的可触区问题
学习目标
- 能够输出文件压缩与文件合并,对前端优化的意义
- 连接传统文件合并与压缩的方法
- 掌握webpack的使用方法
- 能够使用webpack实现文件合并于压缩
传统文件合并:手动合并
传统文件压缩:借助在线工具
文件压缩与合并 — 新技术 webpack
webpack是一个模块打包器,主要作业是打包JavaScript文件,可借助丰富的插件,实现html、css等其他资源的打包
安装cnpm(淘宝镜像可选)
npm install -g cnpm --registry=https://registry.npm.taobao.org
生成package.json文件
npm init y
局部安装webpack
npm install -D webpack webpack-cli
新建webpack.config.js
const path = require('path')
module.exports = {
// 入口
entry: {
index: './src/js/index.js',
},
// 出口
output: {
filename: '[name].js',
path: path.resolve(__dirname, '../out')
}
// 模式
mode: "development"
}
配置package.json
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
//加入以下代码
"start": "webpack --config config/webpack.config.js"
}
运行命令npm run start 便可打包js文件
被依赖的js文件,使用import和export进行处理,引入到响应js文件中,再次打包即可实现js文件的合并
function a() {
console.log('被依赖的js')
}
export default a;
import a from './inde.js'
a()
console.log('不被依赖的js')
再次输入npm run start 便可合并js文件
安装插件html-webpack-plugin
npm install -D html-webpack-plugin
在webpack.config.js
配置文件中引入
const htmlwpPlug = require('html-webpack-plugin')
module.exports = {
plugins: [
new htmlwpPlug({
filename: './cn/index.html',
template: './src/index.html',
chunks: ['index'],
minify: {
collapseWhitespace: true,
removeComments: true
}
})
]
}
根据插件,调整配置信息后,打包运行
css-loader
和style-loader
uglifyjs-webpack-plugin
optimize-css-assets-webpack-plugin
修改相应js文件,引入css文件
mini-css-extract-plugin
完整webpack.config.js文件
const path = require('path')
const htmlwpPlug = require('html-webpack-plugin')
const UglifyJsPlug = require('uglifyjs-webpack-plugin')
const OptimizeCSSAssetsPlug = require('optimize-css-assets-webpack-plugin')
const MiniCSSExtractPlug = require('mini-css-extract-plugin')
module.exports = {
entry: {
index: './src/js/index.js',
},
output: {
filename: '[name].js',
path: path.resolve(__dirname, '../out')
},
mode: "development",
plugins: [
new htmlwpPlug({
filename: './cn/index.html',
template: './src/index.html',
chunks: ['index'],
minify: {
collapseWhitespace: true,
removeComments: true
}
}),
new MiniCSSExtractPlug({
filename: "[name].css",
chunkFilename: "[id].css"
})
],
optimization: {
minimizer: [
new UglifyJsPlug({
cache: true,
parallel: true,
sourceMap: true
}),
new OptimizeCSSAssetsPlug({})
]
},
module:{
rules: [{
test: /\.css$/,
use: [MiniCSSExtractPlug.loader, 'css-loader']
}]
}
}
学习目标
- 能够使用@font-face为文字设置特殊字体
- 掌握呢书字体的”缩小“方法
- 能够根据需求为图片选择合理的格式
- 能够使用在线工具,实现图片压缩与处理
- 掌握webp与srcset的使用方法
- 能够利用背景图合并技术,降低服务器请求次数
传统特殊字体的实现方法与问题
@font-face的使用
@font-face{
font-family: ;
src:
处理特殊字体的工具——fontmin
不同情境下,对于特殊字体的处理方法
图片类型
图片压缩
压缩原则
在线压缩地址
智图:https://zhitu.isux.us
tinypng: https://tinypng.com/
等等
webp与srcset
webp图片类型
webp与jpg的比较
转换webp格式的图片的软件/方法
iSparta软件
智图
背景图片合并技术
学习目标
- 能够将CSS、JS文件放置在合理位置
- 能够说出页面回流与页面重绘
页面回流
当render tree(DOM Tree 和样式结构体组合后构建)中的一部分(或全部)因为元素的规模尺寸,布局,隐藏的改变引起的页面重新渲染(或者交做重新构建绘制)
页面重绘
当render tree中的一些元素需要更新属性,但这些属性之影响元素的外观,风格,而不会影响到元素的布局,此类页面渲染叫做页面重绘
学习目标
通过JS实现图片预加载
掌握按需加载的基本原理和实现方法
<body>
<div id="img">div>
<script>
var box = document.getElementById('box')
var img = document.getElementById('img')
var loadImg = [];
loadImg.push('img/1.jpg')
loadImg.push('img/2.jpg')
loadImg.push('img/3.jpg')
loadImg.push('img/4.jpg')
loadImg.push('img/5.jpg')
var imgsNum = loadImg.length
var nowNum = 0
var nowPer = 0
for (let i = 0; i < imgsNum; i++) {
console.log(i)
var newImg = new Image();
newImg.src = loadImg[i];
newImg.onload = (function(){
nowNum++
img.appendChild(newImg);
nowPer = nowNum/imgsNum *100
console.log(nowPer + '%')
if (nowNum == imgsNum) {
console.log('加载完成')
return
}
})()
}
script>
body>
按需加载HTML内容
<body>
<div id="box">
<script id="hide" type="text/x-template">
<div>
<img src="img/1.jpg" alt="">
<img src="img/2.jpg" alt="">
<img src="img/3.jpg" alt="">
</div>
script>
<div id="con">点击我看效果div>
div>
<script>
var con = document.getElementById('con')
var hide = document.getElementById('hide')
var box = document.getElementById('box')
con.onclick = function(){
box.innerHTML = hide.innerHTML
con.onclick = null
}
script>
body>
按需加载图片
<body>
<div id="box">
<div id="tit">点我加载div>
<div id="con">
<img src="" alt="图片1" data-src="img/1.jpg" alt="">
<img src="" alt="图片1" data-src="img/2.jpg" alt="">
div>
div>
<script>
var imgs = document.getElementById('box').getElementsByTagName('img')
var tit = document.getElementById('tit')
tit.onclick = function(){
var imgLen = imgs.length
for (let i = 0; i < imgLen; i++) {
var relSrc = imgs[i].getAttribute('data-src')
imgs[i].setAttribute('src',relSrc)
}
}
script>
body>
按照整个屏幕进行加载
<textarea id="add1">//具体代码textarea>
利用Ajax实现页面懒加载
核心原理
在符合某种条件时,触发懒加载
使用Ajax实现前后台数据交互,一部请求数据
使用DOM将Ajax异步获取的数据加载到HTML当中
学习目标
- 掌握标签查找(遍历)此时对代码执行速度的影响
- 掌握大量DOM节点操做的处理方法
- 掌握DOM2级时间绑定方法
- 能够合理使用事件委托
- 了解利用css与css3属性实现动画的不同之处
- 掌握函数缓存
- 能使用惰性载入函数实现DOM2级的事件绑定
- 能使用函数柯里化实现DOM2级的事件绑定
- 能借助Canvas,优化图片上传方法
获取标签
遍历查找标签列表的长度
var test = document.getElementById("rest");
var lists = test.document.getElementsByTsgName("li");
var len = lists.length;
for(va i=0; i<len; i++){
console.log('for中具体代码');
}
获取大量数据信息后,DOM节点动态创建方法
var list = document.getElementById("list");
for (var i=0; i<2000; i++) {
list.innerHTML = '- '
+ i + '
var list = document.getElementById("list");
var str = ''
for (var i=0; i<2000; i++) {
str += '- '
+ i + ''
};
list.innerHTML = str;
DOM0级 事件绑定问题:同标签 类型事件只能绑定一次
DOM2级 事件绑定: 同标签同类型事件可绑定多次
DOM2级 事件绑定方法
事件委托:减少功能函数的数量
事件委托基本原理
// 传统DOM0级事件绑定
var list = document.getElementById("list");
var listItems = list.getElementBytagName("li");
var listlen = listItems.length;
for(var i = 0; i < listlen; i++) {
listItems[i].onclick = function() {
for(var i = 0; i < listlen; i++) {
listItems[i].className = '';
}
this.className = 'select'
}
}
// 事件委托
list.onclick = function(e) {
var target = e.target;
for(var i = 0; i < listlen; i++) {
listItems[i].className = '';
};
target.className = 'select';
}
//DOM2级事件绑定
list.addEventlistener('click',function(e) {
var target = e.target;
for(var i = 0; i < listlen; i++) {
listItems[i].className = '';
};
target.className = 'select';
}),false);
传统实现方法
<body>
<div id="btn1">btn1div>
<div id="btn2">btn2div>
<script>
var btn1 = document.getElementById('btn1')
var btn2 = document.getElementById('btn2')
// 传统事件绑定
function eHandler(ele, type, ftn) {
if (window.addEventListener) {
ele.addEventListener(type, function(e){
ftn.call(ele, e)
},false);
}else if (window.attachEvent) {
ele.attachEvent('on' + type, function (e) {
ftn.call(ele, e)
})
}
}
eHandler(btn1, 'click', function() {
console.log('元素被点击了')
});
eHandler(btn2, 'click', function() {
console.log('第二个div被点击了')
});
script>
body>
毒性载入函数
<body>
<div id="btn1">btn1div>
<div id="btn2">btn2div>
<script>
var btn1 = document.getElementById('btn1')
var btn2 = document.getElementById('btn2')
//惰性载入函数
function eHandler(ele, type, ftn) {
if (window.addEventListener) {
console.log('if语句被执行')
eHandler = function(ele, type, ftn){
ele.addEventListener(type, function(e){
ftn.call(ele, e)
},false)
}
}else if (window.attachEvent) {
console.log('IE if语句被执行')
eHandler = function(ele, type, ftn){
ele.attachEvent('on' + type, function(e) {
ftn.call(ele, e)
})
}
}
return eHandler(ele, type, ftn)
}
eHandler(btn1, 'click', function() {
console.log('元素被点击了')
});
eHandler(btn2, 'click', function() {
console.log('第二个div被点击了')
});
script>
body>
函数柯里化
<body>
<div id="btn1">btn1div>
<div id="btn2">btn2div>
<script>
var btn1 = document.getElementById('btn1')
var btn2 = document.getElementById('btn2')
//函数柯里化
var addEvent = (function(){
if (window.addEventListener) {
console.log('是否运行多次')
return function(ele, type, ftn){
ele.addEventListener(type, function(e){
ftn.call(ele, e)
},false)
}
}else if (window.attachEvent) {
console.log('是否运行多次')
return function(ele, type, ftn){
ele.attachEvent('on' + type, function(e) {
ftn.call(ele, e)
})
}
}
})();
addEvent(btn1, 'click', function() {
console.log('元素被点击了')
});
addEvent(btn2, 'click', function() {
console.log('第二个div被点击了')
});
script>
body>
Canvas优化图片上传
<body>
<div>
<img id="pic" src="" alt="">
div>
<div>
<input type="file" id="fileBtn">
div>
<script>
var pic = document.getElementById('pic')
var fileBtn = document.getElementById('fileBtn')
var canvas = document.createElement('canvas')
var context = canvas.getContext('2d')
var relPic = new Image()
fileBtn.onchange = function (e) {
showPic(e)
}
function showPic(e) {
var fileUrl = fileBtn.files[0]
var fileType = fileUrl.type
var reader = new FileReader()
reader.readAsDataURL(fileUrl)
reader.onload = function(e) {
var fileSrc = e.target.result
relPic.src = fileSrc
relPic.onload = getSize
}
function getSize() {
var w = this.width
var h = this.height
var imgSize = 400
var cw = w
var ch = h
if(cw >= ch) {
cw = imgSize
ch = cw / w * h
}else{
ch = imgSize
cw = ch / h * w
}
canvas.width = cw
canvas.height = ch
context.clearRect(0, 0, 400, 400)
context.drawImage(this, 0, 0, cw, ch)
var newImg = canvas.toDataURL(fileType, 0.8)
pic.setAttribute('src', newImg)
}
}
script>
body>
面向对象案例功能需求
// 面向过程传统方法
var name = "张三"
var age = 28
var info
function changeInfo() {
if (age < 18) {
info = name + '未满18岁'
}else{
info = name + '当前的年龄为:' + age
}
}
changeInfo()
console.log(info)
面向对象 — 使用对象实现初步优化
// 面向对象
var peo = {
name: "张三",
age: 28,
info: '',
changeInfo: function() {
if (this.age < 18) {
this.info = this.name + '未满18周岁'
}else {
this.info = this.name + '当前的年龄为:' + this.age
}
}
}
peo.changeInfo()
console.log(peo.info)
面向对象 — 工厂模式
function user(name, age) {
var peo = {};
peo.name = name
peo.age = age
peo.info = ""
peo.changeInfo = function() {
if (this.age < 18) {
this.info = this.name + '未满18周岁'
}else {
this.info = this.name + '当前的年龄为:' + this.age
}
}
return peo
}
var peo = user('张三', 28)
peo.changeInfo()
console.log(peo.info)
面向对象 — 构造模式与原型模式
//构造模式
function User(name, age) {
this.name = name
this.age = age
this.info = ""
this.changeInfo = function() {
if (this.age < 18) {
this.info = this.name + '未满18周岁'
}else {
this.info = this.name + '当前的年龄为:' + this.age
}
}
}
var peo = new User('张三', 28)
peo.changeInfo()
console.log(peo.info)
//原型模式
function User() {
}
User.prototype.name = 'user'
User.prototype.age = 8
User.prototype.info = ''
User.prototype.changeInfo = function() {
if (this.age < 18) {
this.info = this.name + '未满18周岁'
}else {
this.info = this.name + '当前的年龄为:' + this.age
}
}
var peo = new User()
peo.name = '张三'
peo.age = 28
peo.changeInfo()
console.log(peo.info)
面向对象 — 混合模式
// 混合模式
function User(name, age) {
this.name = name
this.age = age
this.info = ""
}
User.property.changeInfo = function() {
if (this.age < 18) {
this.info = this.name + '未满18周岁'
}else {
this.info = this.name + '当前的年龄为:' + this.age
}
}
var peo = new User('张三', 28)
peo.changeInfo()
console.log(peo.info)