• 浏览器环境


     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标签加载协议

    1. src属性

    默认http协议

    <script async src="localhost:3000/js/1.js"></script>

    默认页面本身的协议(当前页面是https,下面js就是https)

    <script async src="//localhost:3000/js/1.js"></script>

    2. crossorigin属性

    有两个枚举值。anonymous和use-credentials

    crossorigin="anonymous" //跨域不发送凭证 相当于直接使用crossorigin
    crossorigin="use-credentials" // 跨域发送凭证

    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)
  • 相关阅读:
    Flask——中间件,蓝图
    导出项目环境 requiredments
    Flask——路由正则,Request方法,Response方法,cookies,session,闪现,请求扩展
    Flask——路由,jinja2,三板斧,前端数据传输,反向解析,配置文件,转换器,路由本质,CBV
    Linux——权限,二进制安装,进程管理,系统服务
    Python基础概括
    echarts 使用
    Celery 使用
    第五周总结
    软件的需求为什么会出现差别
  • 原文地址:https://www.cnblogs.com/lyraLee/p/11878045.html
Copyright © 2020-2023  润新知