《一常用图片优化方法》
关于加载优化之图片优化技巧 详细可参考该文章https://juejin.im/post/5d64c47e6fb9a06b0a2783ff?utm_source=gold_browser_extension
1,图片与css: 使用css效果,css动画。替代一些图片或者是js动画,js动画没有css来的简单,css动画还可以通过animationend,translationend事件来监听动画结束,但是js不可以。css效果可以提供与分辨率,缩放无关的清晰度效果,占用空间也更小。
2, 无法避免的图片,如何选择?
jpg全名jpeg,以24位颜色存储单个位图,容易失真,适合颜色丰富的图片
png大,适合活动图片,需要清晰的显示色彩丰富的图片
gif唯一的较通用的动画图
svg可以缩放矢量图,体积小
未来apng和webp
3,图片加载效果 :一种是先模糊后清晰,一种是很清晰,但是逐行加载,原理是图片压缩算法不同,前者是小波算法,后者是离散余弦变换,浏览器只是根据图片压缩算法来选择渲染算法,压缩算法存在文件头部,我们不能 通过改变图片后缀名影响加载方式。
4,小的icon,使用sprites替代
在线制作: http://alloyteam.github.io/gopng
http://fis.baidu.com
http://gruntjs.com
5,响应式动态图片加载(SDK)
1需要一个默认图片,
2需要屏幕分辨率信息给服务器
3服务给我们更优质的图片
6,未来方法
新元素
《二常用视频优化方法》
video标签/ flash播放
目前方案,flash和h5 video结合,组成完整方案,比如:
flowplayer功能简洁,使用方便
https://flowplayer.org/player
videojs功能强大,使用复杂
https://videojs.com
浏览器会默认将多媒体资源放置到页面的最后加载,这就需要我们处理资源前置,对于视频直播网站,用户更需要的进入就能直观看视频,而不是去互动弹幕聊天等其他功能。
解决方案:用加载样式表的方式引入媒体资源,这样浏览器就不会把资源当成媒体资源而后置加载。
下一个目标优化:利用浏览器的内存,提高加载速度。
《三常用缓存方式》
cookies/sessionstroage/localstroage/userData/openDatabase等业内常用的储存方式。
技术选型:什么问题?通用方案?方案能解决问题?我们自己的方案,需要其他的方案来融合?自己造轮子?
1,sessionstroage:临时存储中心,小,不能跨页面,关闭页签会丢失(同页面打开同标签也不能拿到)
注意sessionstroage.getItem(‘keys’)和sessionstroage.keys获取值方式不一样,我们需要对null和undefined都做判断。
2,localstroage:长期存储只是对于同一个浏览器,换言之,不同浏览器是读不到在其他浏览器的缓存的,同一浏览器关闭不影响,非手动不清除会一直存在,存储有限制,ie9,ie10不支持
3,cookies:兼容性最好的本地存储,常见用于保存登录态, 大小限制,每次发送请求,请求头都会携带cookie过去。
4,userData:ie的私有存储中心,单文件限制128kb,一个域名下限制1024kb,在受限制站点分别是64kb和640kb
5,openDatabase:浏览器的完整的数据库,
创建,增删改查
实例演示数据库操作的api
<h1>opendatabse数据库操作</h1>
<button id="btn-create">创建user数据表</button>
<button id="btn-insert">插入数据</button>
<button id="btn-query">查询数据</button>
<button id="btn-update">修改数据</button>
<button id="btn-delete">删除数据</button>
<button id="btn-drop">删除user数据表</button>
<script type="text/javascript">
let findId = id => document.getElementById(id);
//模拟一条user数据
let user = {
username: "vv",
password: "123456",
info: "程序员"
};
/**
* 创建数据库 或者此数据库已经存在 那么就是打开数据库
* name: 数据库名称
* version: 版本号
* displayName: 对数据库的描述
* estimatedSize: 设置数据的大小
* creationCallback: 回调函数(可省略)
*/
let db = openDatabase("MySql", "1.0", "我的数据库描述", 1024 * 1024);
let result = db ? "数据库创建成功" : "数据库创建失败";
console.log(result);
const USER_TABLE_SQL = "create table if not exists userTable (id integer primary key autoincrement,username varchar(12)," +
"password varchar(16),info text)";
//创建数据表
function createTable() {
db.transaction(tx => {
tx.executeSql(USER_TABLE_SQL, [],
(tx, result) => {
alert('创建user表成功:' + result);
}, (tx, error) => {
alert('创建user表失败:' + error.message);
})
})
}
const INSERT_USER_SQL = "insert into userTable (username, password,info) values(?,?,?)";
//插入数据
function insertData(user) {
db.transaction(tx => {
tx.executeSql(INSERT_USER_SQL,
[user.username, user.password, user.info],
(tx, result) => {
alert('添加数据成功:');
}, (tx, error) => {
alert('添加数据失败:' + error.message);
})
})
}
const QUERY_USER_SQL = "select * from userTable";
//查询数据
function queryData() {
db.transaction(tx => {
tx.executeSql(QUERY_USER_SQL, [],
(tx, result) => {
console.log(result);
},
(tx, error) => {
console.log('查询失败: ' + error.message)
})
})
}
const UPDATE_USER_SQL = "update userTable set password = ? where username = ?";
//修改数据
function updateData(user) {
db.transaction(tx => {
tx.executeSql(UPDATE_USER_SQL, [user.password, user.username],
(tx, result) => {
alert("修改数据成功")
}, (tx, error) => {
alert("修改数据失败:" + error.message)
})
})
}
const DELETE_USER_SQL = "delete from userTable where username = ?";
//删除数据
function deleteData(user) {
db.transaction(tx => {
tx.executeSql(DELETE_USER_SQL, [user.username],
(transaction, resultSet) => {
alert("删除数据成功")
}, (transaction, error) => {
alert("删除数据失败:" + error.message)
})
});
}
const DROP_USER_SQL = "drop table userTable";
//删除数据表
function dropTable() {
db.transaction(tx => {
tx.executeSql(DROP_USER_SQL, [],
(transaction, resultSet) => {
alert("删除数据表成功")
}, (transaction, error) => {
alert("删除数据表失败:" + error.message)
})
})
}
/**
* 点击事件 增删查改
*/
let btnCreate = findId("btn-create");
let btnInsert = findId("btn-insert");
let btnQuery = findId("btn-query");
let btnUpdate = findId("btn-update");
let btnDelete = findId("btn-delete");
let btnDrop = findId("btn-drop");
btnCreate.onclick = () => createTable();
btnInsert.onclick = () => insertData(user);
btnQuery.onclick = () => queryData();
btnUpdate.onclick = () => {
user.password = "111666666"; //修改密码
updateData(user);
};
btnDelete.onclick = () => deleteData(user);
btnDrop.onclick = () => dropTable();
</script>
</body>
</html>
————————————————
版权声明:本文为CSDN博主「LQ-刘强」的原创文章
原文链接:https://blog.csdn.net/qq_33429583/article/details/79674597
《四做一个通用的缓存sdk》
封装一个本地缓存通用的tools出来。
目标:提取用户第一时间看到的,提取页面第一时间执行的
1,初始化数据的js,或者依赖的类库
2,用户进入页面需要看到的页面的结构
3,拉去新资源,存储新资源,根据版本迭代,置换过期资源。
功能:
1,网络交互,xhr ; 2,本地存储,localSDK; 3,缓存展示,浏览器dom解析器
window.Xhrfactory = function () {
this.init.apply(this, arguments);
};
// 网络xhr
window.Xhrfactory.prototype = {
init: function () {
this.xhr = this.create();
},
create: function () {
var xhr = null;
if (window.XMLHttpRequest) {
xhr = new XMLHttpRequest();
} else if (window.ActiveXobject) {
xhr = new ActiveXObject('Msml2.Xmlhttp');
} else {
xhr = new ActiveXObject('Microsoft.Xmlhttp');
}
return xhr;
},
readystate: function (callback) {
this.xhr.onreadystatechange = function () {
if (this.readyState === 4 && this.status === 200) {
callback(this.responseText);
}
}
},
para: function (data) {
var datastr = '';
if (data && Object.prototype.toString.call(data) === '[object Object]') {
for (var key in data) {
datastr += (key + '=' + data[key] + '&');
}
if (datastr) datastr = datastr.slice(0, -1);
}
},
get: function (url, data, callback) {
this.readystate(callback);
var newurl = url;
var datastr = this.para(data);
newurl = url + '?' + datastr;
this.xhr.open('get', newurl, true);
this.xhr.send(null);
}
}
//由后台控制缓存
var localStorageSign = 'on';
//版本控制
var resourceVersion = '1221211212121';
// 本地sdk
window.mLocalSdk = {
resourceJavascriptList =[
{ scriptId: '1', url: "lib.js", type: 'javascript' },
{ scriptId: '2', url: "common.js", type: 'javascript' },
{ scriptId: '3', url: "index.js", type: 'javascript' }
],
needUpdate: (function () {
return localStorage.getItem('resourceVersion') === resourceVersion;
})(),
isIE: (function () {
var userAgent = navigator.userAgent; //取得浏览器的userAgent字符串
var isIE = userAgent.indexOf("compatible") > -1 && userAgent.indexOf("MSIE") > -1; //判断是否IE<11浏览器
var isEdge = userAgent.indexOf("Edge") > -1 && !isIE; //判断是否IE的Edge浏览器
var isIE11 = userAgent.indexOf('Trident') > -1 && userAgent.indexOf("rv:11.0") > -1;
if (isIE || isEdge || isIE11) {
return true;
} else {
return false;
}
})(),
checkHedge: function () {
var localStroageLength = localStorage.length;
var localStorageSize = 0;
for (var i = 0; i < localStorageSize; i++) {
var key = localStorage.key(i);
localStorageSize += localStorage.getItem(key).length;
}
return localStorageSize;
},
startup: function () {
var self = this;
if (localStorageSign === 'on' && this.isIE && window.localStorage) {
if (this.needUpdate) {
return (function () {
for (var i = 0; i < self.resourceJavascriptList.length; i++) {
//获取本地缓存列表,输入到html
var scriptId = self.resourceJavascriptList[i]['scriptId'];
//把我们的列表中的js渲染到页面, 读取本地文件
window.mDomUtils.addJavascriptByInline(scriptId);
}
})();
} else {
//把网络获取的js渲染html
return (function () {
// save 请求到的js
self.saveSdk();
for (var i = 0; i < self.resourceJavascriptList.length; i++) {
//获取本地缓存列表,输入到html
var scriptId = self.resourceJavascriptList[i]['scriptId'];
//把我们的列表中的js渲染到页面, 读取本地文件
window.mDomUtils.addJavascriptByInline(scriptId);
}
})();
}
} else {
//把网络获取的js渲染html
// 原始方法加载js
return (function () {
for (var i = 0; i < self.resourceJavascriptList.length; i++) {
//获取本地缓存列表,输入到html
var scriptId = self.resourceJavascriptList[i]['scriptId'];
//把我们的列表中的js渲染到页面, 读取本地文件
window.mDomUtils.addJavascriptByLink(scriptId, url);
}
})();
}
},
//写入本地localstorage
saveSdk: function () {
try {
localStorage.setItem('resourceVersion', resourceVersion)
} catch (oException) {
if (oException.name === 'QuotaExceededError') {
localStorage.clear();
localStorage.setItem('resourceVersion', resourceVersion);
}
}
for (var i = 0; i < this.resourceJavascriptList.length; i++) {
let self = this;
(function(i){
var scriptId = self.resourceJavascriptList[i]['scriptId'];
var xhr = new Xhrfactory();
xhr.get(self.resourceJavascriptList[i]['url'], null, function (data) {
try {
localStorage.setItem(scriptId, data);
} catch (oException) {
if (oException.name === 'QuotaExceededError') {
localStorage.clear();
localStorage.setItem(scriptId, data);
}
}
});
})(i);
// addhtml 加载到页面中
}
}
};
window.mDomUtils = {
// 内联添加script
addJavascriptByInline: function (scriptId) {
var script = document.createElement('script');
script.setAttribute('type', 'text/javascript');
script.id = scriptId;
var heads = document.getElementsByTagName('head');
if (heads.length) {
heads[0].appendChild(script);
} else {
document.documentElement.appendChild(script);
}
script.innerHTML = localStorage.getItem(scriptId);
},
// 外链添加script
addJavascriptByLink: function (scriptId, url) {
var script = document.createElement('script');
script.setAttribute('type', 'text/javascript');
script.setAttribute('src', url);
script.id = scriptId;
var heads = document.getElementsByTagName('head');
if (heads.length) {
heads[0].appendChild(script);
} else {
document.documentElement.appendChild(script);
}
},
addCssByLink: function (url) {
var link = document.createElement('link');
link.setAttribute('rel', 'stylesheet');
link.setAttribute('type', 'text/css');
link.setAttribute('href', url);
if(link.stylesheet) {
// ie
link.stylesheet.cssText = cssString;
}else{
// w3c
var cssText = doc.createTextNode(cssString);
link.appendChild(cssText);
}
var heads = document.getElementsByTagName('head');
if (heads.length) {
heads[0].appendChild(link);
} else {
document.documentElement.appendChild(link);
}
}
};
//展示缓存
//单文件9000多字符限制sdk
《五高性能dom》
这里主要涉及造成性能优化dom时候,主要碰到的重绘和回流问题,介绍他们的原因和解决方案,最后实际代码来验证。
为什么写高性能dom?
站点的网络消耗,dom初始化(浏览器),dom结构及操作(人为),js执行(浏览器),js逻辑(人为)
关于reflow和repaint,避免回流和重绘。
改变字体,修改样式表,内容改变比如input,激活css伪类,操作dom,offsetwidth,offsetheight, style值修改