浏览器环境
1. js代码嵌入网页的方式
1. script标签嵌入脚本
script标签有个属性type,用于指定脚本的类型;
1. "text/javascript": 默认值,指定运行的是js代码
<script> </script>
2. "application/javascript": 在较新的浏览器中,指定是JS代码
<script src="application/javascript"> //TODO </script>
3. "text/babel": 指定脚本是JSX语法的代码;
使用前提是需要引入
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
babel文件将JSX语法中的标签,解析为React.createElement();如果不引入,则浏览器不识别text/babel类型;
另外,由于babel引入了React,则需要引入React文件;然后想要渲染需要ReactDOM文件;
<script src="https://unpkg.com/react@16/umd/react.production.min.js" crossorigin></script> <script src="https://unpkg.com/react-dom@16/umd/react-dom.production.min.js" crossorigin></script>
示例:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>JSX</title> <script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script> <script src="https://unpkg.com/react@16/umd/react.production.min.js" crossorigin></script> <script src="https://unpkg.com/react-dom@16/umd/react-dom.production.min.js" crossorigin></script> </script> </head> <body> <div id="root"></div> <script type="text/babel"> const a = [1,2].map(i => <div>{i}</div>); ReactDOM.render(a,root); </script> </body> </html>
4. 其他值: 不是上面的三种类型,浏览器不认识,则不执行,将其当作普通的标签。
可以获取标签内部的内容。element.text
<script type="x-custom"> console.log('sth'); </script>
2. script引入外部脚本
通过src属性,引入外部脚本。如果脚本文件内容使用了非英文字符,还要注明使用的字符编码。
脚本文件内容必须是纯js内容。外联script标签中间的内容会被忽略。
<script charset="utf-8" src="./test.js" ></script>
还有一个integrity属性: 内容是外部脚本的hash签名,验证脚本的一致性,用于防止外部修改外联脚本。
<script
src="/assets/application.js" integrity="sha256-TvVUHzSfftWg1rcfL6TIJ0XKEGrgLyEq6lEpcmrG9qs="> </script>
如果修改了外部脚本,签名将不再匹配,浏览器会拒绝加载。
3. 事件属性
<div id="root" onclick="const a = test();console.log(a)">ClickMe</div> <script type="text/babel"> function test() { return 5; } </script>
4. javascript协议
a标签的href属性,一般放置URL。但是也支持javacript协议,此时触发a标签,会执行协议后的js代码。
<a href="javascript: console.log(1)">点击</a> // 点击后,在控制台打印1
如果javascript:协议后,返回一个字符串,那么,原有文档消失,新建一个文档,文档内容只有该字符串。
<a href="javascript:(1).toString()">点击</a>
另: 浏览器的地址栏也支持该协议。
如果不想页面跳转,不想生成的新的文档取代原来的文档,可以使用void或者void 0;
<a href="javascript: void (1).toString()">点击</a>
或者
<a href="javascript: (1).toString(); void 0;">点击</a>
应用:
该协议可以用于标签栏。
<a href="http://www.baidu.com">百度</a>//百度的标签 // 操作: 鼠标可以直接拖动该链接到书签栏
也可以自定义书签栏,实现某个自定义功能
// 实现点击查看当前实现;可以将其拖入书签栏 <a href="javascript: alert(new Date().toLocaleString())">当前时间</a>
2. script标签加载协议
默认http协议
<script async src="localhost:3000/js/1.js"></script>
默认页面本身的协议(当前页面是https,下面js就是https)
<script async src="//localhost:3000/js/1.js"></script>
3. 浏览器组成
浏览器核心是:渲染引擎和js引擎。
1. 渲染引擎
1. 解析代码;HTML->DOM, CSS->CSSOM 2. 合并成渲染树 3. 布局 4. 绘制
以上步骤不是严格按照顺序执行;有时第一部分未完成,也会执行后面的步骤渲染。
2. 重流和重绘
1. 定义
渲染树转为网页布局,称为“布局流”(flow);
布局显示到页面,称为“绘制”(paint);
脚本操作或者样式表操作,都可能触发重流(reflow)或者重绘(repaint);
重流肯定导致重绘;重绘不一定需要重流。
2. 特征
浏览器会累计DOM变动
var foo = document.getElementById('foobar'); foo.style.color = 'blue'; //触发重绘 foo.style.marginTop = '30px'; //触发重流和重绘
上面代码虽然触发两次重绘,但是实际只会执行一次。因为浏览器累计变动。
基于DOM变动累计,优化如下:
示例:
<ul id="list"></ul> <script> const list = document.querySelector('#list'); const fruits = ['Apple', 'Orange', 'Banana', 'Melon']; fruits.forEach(fruit => { const li = document.createElement('li'); // 创建,读取DOM li.innerHTML = fruit; list.appendChild(li); //写入DOM }); </script> //混写会导致不停的重流重绘,每插入一个,重新渲染一次
2. 使用DocumentFragment或者VituralDOM
DocumentFragment不是真实的DOM树的一部分,它不会触发重新渲染。
示例:
// 解决第一部分的问题 const list = document.querySelector('#list'); const fruits = ['Apple', 'Orange', 'Banana', 'Melon']; const fragment = document.createDocumentFragment(); fruits.forEach(fruit => { const li = document.createElement('li'); li.innerHTML = fruit; fragment.appendChild(li); // 不会触发重新渲染 }); list.appendChild(fragment); //相当于一次性写入;即所有写入操作写在一起;只执行一次重流重绘
3. 使用window.requestAnimationFrame()
会将变动累计到下一次重流时执行;不会立即要求页面重流
// 读写DOM混写在一起,导致不停的重流重绘 function doubleHeight(element) { var currentHeight = element.clientHeight; //读取DOM element.style.height = (currentHeight * 2) + 'px'; //样式写入DOM } all_my_elements.forEach(doubleHeight); // 重绘代价低;只执行一次重流重绘 function doubleHeight(element) { var currentHeight = element.clientHeight; // 把所有的写操作累计在一起;下次重流时一次性执行完成 window.requestAnimationFrame(function () { element.style.height = (currentHeight * 2) + 'px'; }); } all_my_elements.forEach(doubleHeight);
4. 将样式变动写在一起
样式修改不要一项一项的修改;使用css的class一次性改变样式;。
5. 定位使用absolute或者fixed定位
可以减少对其他元素的影响;flex布局开销就会比较大
6. 隐藏元素使用visibility: hidden
隐藏元素不要使用display属性;它会导致布局变动;
而visibility属性不会更改文档的布局。只会重绘。
切换显示使用visibility: visible;
如果父元素设为hidden, 子元素设为visible; 子元素可见。
3. js引擎
js处理过程:
1. 词法分析 2. 语法分析->语法树 3. 生成字节码 4. 字节码在js引擎(虚拟机)上,在运行时通过js引擎的即时编译器(JIT)成机器码,并缓存编译结果。 // 或者 直接将源码通过js引擎的即时编译器编译成机器码
js引擎也可以叫做虚拟机。现有常见虚拟机
Chakra(Microsoft Internet Explorer) Nitro/JavaScript Core (Safari) Carakan (Opera) SpiderMonkey (Firefox) V8 (Chrome, Chromium)
原文地址:https://www.cnblogs.com/lyraLee/p/11878045.html
- 如何通过iframe调用其他页面的内容
- WCF 学习总结1 -- 简单实例
- Java8 + Tomcat8 实现Websocket 例子
- Python Syslog Server 开发实例
- WCF 学习总结2 -- 配置WCF
- SQLite事务 SQLite插入多条语句为什么这么慢?.net (C#)
- Linux 应用程序开发入门
- LINQ to XML LINQ学习第一篇
- PHP 安全与性能
- Extjs 项目中常用的小技巧,也许你用得着(5)--设置 Ext.data.Store 传参的请求方式
- WPF备忘录(5)怎样修改模板中的控件
- Linux 系统与数据库安全
- 使用委托实现同步回调与异步回调
- Application Firewall Design
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- Apache跨域资源访问报错问题解决方案
- Windows Telemetry服务特权提升
- 滥用DComposition在外部窗口上渲染
- 通过LUMP_PAKFILE的源引擎内存损坏
- MongoDB Change Stream之一——上手及初体验
- MongoDB 慢日志字段解析
- leetcode哈希表之第一个只出现一次的字符
- 转录组RNA-Seq使用docker+bioconda搭建分析环境
- 企业自建GitLab代码仓库安装与基础配置使用
- 全网最全的数据库操作命令,一口气从头看到尾,蛮有收获的!
- 【C++】 使用sort函数进行容器排序
- 宝塔如何安装 MDClub
- Jackson 的 JsonManagedReference 和 JsonBackReference 注解
- leetcode哈希表之独一无二的出现次数
- Vue 网站首页加载优化