浏览器环境

时间:2019-11-17
本文章向大家介绍浏览器环境,主要包括浏览器环境使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

 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变动累计,优化如下:

1.不要混写读取DOM和写入DOM
尽量读取DOM写在一起,写入DOM写在一起;这样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