首页

Webpack:知识点总结以及遇到问题的处理办法

前端达人

文章目录

0.官方文档:

1.webpack概述:

2.webpack的基本使用:

3.在项目中安装和配置 webpack:

4.配置自定义打包的自定义入口和出口:

4.配置自动打包功能:

5.配置生成预览页面功能:

6.配置自动打包相关参数:

7.webpack 中的加载器:

8.loader加载器的基本使用:

9.Vue单文件组件:

10.webpack 打包发布:

11.以上所有配置 webpack.config.js 截图


1.webpack概述:
webpack是一个流行的前端项目构建工具(打包工具) ,可以解决当前web开发中所面临的困境
webpack提供了友好的模块化支持,以及代码压缩混淆、处理js兼容问题、性能优化等强大的功能,从而让程序员把工作的重心放到具体的功能实现上,提高了开发效率和项目的可维护性

2.webpack的基本使用:
2.1:打开终端运行命令 npm init -y 初始化包管理配置文件 package.json

2.2:新建 src 源文件目录(里面放程序员自己写的代码比如 html css js images …)

2.3:如果需要引入 jquery 库 终端运行以下命令npm install jquery -S 安装 jquery

自己在src文件夹中创建 index.js 引入下载的jquery包import $ from 'jquery'

3.在项目中安装和配置 webpack:
3.1:终端运行 npm install webpack-cli -D 命令,安装webpack相关的包

这里要注意一个问题 : package.json 和 package-lock.json 文件里的名字默认为 “name”=“webpack”,在配置 webpack-cli 之前要把name 改成 其他名字 比如 “name”=“webpack_” 不然的话为出现无法安装的问题

具体可点击这里 Webpack依赖包安装问题解决方案
3.2:在项目根目录中 ,创建名为 webpack.config.js 的 webpack 配置文件

3.3:在 webpack.config.js 中,初始化一下基本配置

建议选择 development (打包速度快,体积大),项目上线是才改成 production (如果选择production会进行代码的压缩和混淆,打包速度慢,体积小)

3.4:在package.json中的 script节点 新增一个dev脚本 值为 webpack ,就可以实现打包功能



  • 在终端运行命令:npm run dev 就可以打包 默认打包成main.js在 dist文件夹中

  • src自己新建的index.html 中引入打包后的 js




属性描述符与Proxy的区别&Vue3.0为何改用Proxy

前端达人

属性描述符

什么是属性描述符?

属性描述符就是一个属性除了属性名与属性值之外的其他相关信息

通过Object.getOwnPropertyDescriptor(对象, 属性名)可以得到一个对象的某个属性的属性描述符

let obj = {
    a: 1
}
console.log(Object.getOwnPropertyDescriptor(obj, 'a'));
// {
//     value: 1,
//     writable: true,
//     enumerable: true,
//     configurable: true
// }

通过Object.getOwnPropertyDescriptors(对象)可以得到某个对象的所有属性描述符

let obj = {
    a: 1,
    b: 2
}
console.log(Object.getOwnPropertyDescriptors(obj));
// {
//     a: {
//         value: 1, 
//         writable: true,
//         enumerable: true,
//         configurable: true
//     }
//     b: {
//         value: 2, 
//         writable: true, 
//         enumerable: true, 
//         configurable: true
//     }
// }


接下来,说一说每一个属性描述符的作用

value-属性值

不多逼逼

configurable-属性描述符是否可被修改

当我们设置configurable为false以后,再去修改属性描述符的话,会报错


let obj = {
    a: 1,
    b: 2
}
Object.defineProperty(obj, 'a', {
    value: 'a',
    configurable: false
})
Object.defineProperty(obj, 'a', {
    value: 'a',
    configurable: true
})
// Uncaught TypeError: Cannot redefine property: a
//    at Function.defineProperty (<anonymous>)



enumerable-该属性是否可被枚举

当设置一个属性的enumerable为false时,该属性不可被forin循环
但是不影响forof循环,因为forof循环看有没有Symbol(Symbol.iterator)
forin循环的是属性名,forof循环的是属性值


前端学习之JavaScript DOM以及DOM操作的基础知识

前端达人

在了解了javascript的语言基础和特性后

javascript真正大放光彩的地方来了——这就是javascript DOM


Javascript DOM
DOM(Document Object Model),文档对象模型。

是W3C组织推荐的处理可扩展标记语言(HTML或者XML)的标准编程接口;W3C已经定义了一系列DOM接口,通过这些DOM接口可以改变网页的内容、结构和样式。

简单的说就是一套操作文档内容的方法。

需要注意的是,我们需要把DOM当作一个整体,不能分割看待,即DOM(文档对象模型)是一套操作文档内容的方法。


  • 文档:一个页面就是一个文档,DOM中使用document表示
  • 元素:页面中的所有标签都是元素,DOM中使用element表示
  • 节点:网页中的所有内容都是节点(标签、属性、文本、注释等),DOM中使用node表示

DOM把以上内容看作都是对象

<!DOCTYPE html>
<html>
<head>
    <title>Shopping list</title>
    <meta charset="utf-8">
</head>
<body>
<h1>What to buy</h1>
<p id="buy" title="a gentle reminder">Don't forget to buy this stuff</p>
<ul id="purchases">
    <li>A tin od beans</li>
    <li>Cheese</li>
    <li>Milk</li>
</ul>
</body>
</html>



用树表示这个网页的结构:

aHR0cHM6Ly9pbWcyMDE4LmNuYmxvZ3MuY29tL2ktYmV0YS8xODQ2ODAyLzIwMTkxMi8xODQ2ODAyLTIwMTkxMjIzMTcxMDI5MTY1LTExNTE0OTgxMDMucG5n.jpg

1、获取DOM四种基本方法
1、getElementById()

2、getElementsByTagname()

3、getAttribute()

4、setAttribute()

 

常用的两种解析:

1. getElementById():

参数:元素的ID值。 (元素节点简称元素) 
返回值:一个有指定ID的元素对象(元素是对象) 
注:这个方法是与document对象相关联,只能由document对象调用。 
用法:document.getElementById(Id) 

例:

<!DOCTYPE html>
<html lang="zh">

<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>Document</title>
</head>

<body>
    <div id="time">2020-04-16</div>
    <script>
        // 1. 因为我们文档页面从上往下加载,所以先得有标签 所以我们script写到标签的下面
        // 2. get 获得 element 元素 by 通过 驼峰命名法 
        // 3. 参数 id是大小写敏感的字符串
        // 4. 返回的是一个元素对象
        var timer = document.getElementById('time');
        console.log(timer);
        console.log(typeof timer);
        // 5. console.dir 打印我们返回的元素对象 更好的查看里面的属性和方法
        console.dir(timer);
    </script>
</body>

</html>




看一下控制台打印的是什么

20200416221227181.png


可以看到 console.log(timer)打印出来的是整个div标签

timer类型是个对象

 

2. getElementsByTagName():

参数:元素名
返回值:一个对象数组。这个数组里每个元素都是对象,每个对象分别对应着文档里给定标签的一个元素。
注:这个方法可和一般元素关联。这个方法允许我们把通配符当作它的参数,返回在某份html文档里总共有多少个元素节点。
用法:element.getElementsByTagName(TagName) 

例:

var items=document.getElementsByTagName("li");
items.length;//3
document.getElementsByTagName(“*”);//12
 

 

2、事件基础
3.1 事件概述
JavaScript使我们有能力创建动态页面,而事件是可以被JavaScript侦测到的行为。

简单理解:触发——>响应机制

网页中每个元素都可以产生某些可以触发JavaScript的事件,例如,我们可以在用户点击某按钮产生一个事件,然后去执行某些操作

3.2 事件三要素
事件源 、事件类型、事件处理程序,我们也称为事件三要素

(1) 事件源 事件被触发的对象   谁  
(2) 事件类型  如何触发 什么事件 比如鼠标点击(onclick) 还是鼠标经过 还是键盘按下
(3) 事件处理程序  通过一个函数赋值的方式 完成

代码实例

<!DOCTYPE html>
<html lang="zh">

<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>Document</title>
</head>

<body>
    <button id="btn">唐伯虎</button>
    <script>
        // 点击一个按钮,弹出对话框
        // 1. 事件是有三部分组成  事件源  事件类型  事件处理程序   我们也称为事件三要素
        //(1) 事件源 事件被触发的对象   谁  按钮
        var btn = document.getElementById('btn');
        //(2) 事件类型  如何触发 什么事件 比如鼠标点击(onclick) 还是鼠标经过 还是键盘按下
        //(3) 事件处理程序  通过一个函数赋值的方式 完成
        btn.onclick = function() {
            alert('点秋香');
        }
    </script>
</body>

</html>


运行结果

20200416223238828.png

3.3 执行事件的步骤

1、获取事件源

2、注册事件(绑定事件)

3、添加事件处理程序(采取函数赋值形式)

 

代码实战


        


<!DOCTYPE html>
<html lang="zh">

<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>Document</title>
</head>

<body>
    <div>123</div>
    <script>
        // 执行事件步骤
        // 点击div 控制台输出 我被选中了
        // 1. 获取事件源
        var div = document.querySelector('div');
        // 2.绑定事件 注册事件
        // div.onclick 
        // 3.添加事件处理程序 
        div.onclick = function() {
            console.log('我被选中了');

        }
    </script>
</body>

</html>



常用的DOM事件
onclick事件---当用户点击时执行
onload事件---当用户进入时执行
onunload事件---用用户离开时执行
onmouseover事件---当用户鼠标指针移入时执行
onmouseout事件---当用户鼠标指针移出时执行
onmousedown事件---当用户鼠标摁下时执行
onmouseup事件---当用户鼠标松开时执行
 
————————————————
版权声明:本文为CSDN博主「那是我呐」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_42402867/article/details/105567787

【CSS基础学习】CSS的三大特性

前端达人

文章目录


CSS有三大特性,分别是 继承性,层叠性,优先级。CSS的主要特征是继承性,这里先讲解继承性。

继承性

继承性的使用说明

继承性的描述:
继承性是指被包在内部的标签将拥有外部标签的样式性,即子元素可以继承父类的属性。
例:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        div{
            color: blue;
        }
    </style>
</head>
<body>
    <div>父元素
        <div>子元素
            <p>我依旧是子元素</p>
        </div>
    </div>
</body>
</html>



效果如下:

有图可见,被div包裹住的元素,都具有了div的css样式属性,这被我们称为继承性。

在CSS中以,text-,font-,line-开头的属性都是可以继承的。

CSS继承的局限性
并不是所有的CSS属性都可以被继承的,以下就不具有继承性:

a标签的字体颜色不会被继承,a标签的字体颜色是不会改变的,可以通过页面的的F12可以查看到,a标签是有一个默认的color:-webkit-link;字体颜色属性,所以父元素设置颜色是不能发生改变a标签字体的颜色。
h标签的字体的大小也是不能被继承的,如下代码给父元素在设置一个字体属性20px,再添加一个h标签,在浏览器中可以发现h标签中字体的大小是不会发生改变的,因为h标签中有一个默认的font-size:1.5em;字体大小属性。
div标签的高度如果不设置由内容来绝对(没有内容高度未0),宽度默认由父元素继承过来
边框属性
外边距属性
内边距属性
背景属性
定位属性
布局属性
元素宽高属性
层叠性
层叠性的使用说明
层叠性的表述
所谓层叠性是指多种CSS样式的叠加,例如,当使用内嵌式CSS样式表定义p标记字号大小为12像素,ID选择器定义p标记颜色为红色,那么段落文本将显示为12像素红色,即这两种样式产生了叠加。
例:
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        p{
            font-size: 32px;
        }
    </style>
</head>
<body>
            <p style="color: blue;">我这里体现了层叠性呀</p>
</body>
</html>



使用结论
由于内容有限,但是结论是一定的,所以我直接给出结论:

若多个选择器定义的样式不冲突,则元素应用所有选择器定义的样式。
若多个选择器定义的样式发生冲突(比如:同时定义了字体颜色属性),则CSS按照选择器的优先级,让元素应用优先级搞得选择器样式。
CSS定义的选择器优先级从高到低为:行内样式–>ID样式–>类样式–>标记样式。
如若想直接定义使用哪个样式,不考虑优先级的话,则使用!important,把这个加在样式后面就行了。
优先级
定义CSS样式时,经常出现两个或更多规则应用在同一个元素上,这时就会出现优先级的问题。层叠性和选择器的圈中有很大的关系。

优先级的使用说明
权重分析:

内联样式:如:style="",权重为1000。
ID选择器,如:#content,权重为100。
类,伪类和属性选择器,如.content,权重为10。
标签选择器和伪元素选择器,如div p,权重为1。
继承样式,权重为0。
将基本选择器的权重相加之和,就是权重大小,值越大,权重越高。
计算权重方法
数标签:先数权重最高的标签,然后数第二高权重的标签,以此类推,就会生成一个数组,里面包含四个数字。
比如(0,0,0,0)分别对应(行内式个数,id选择器个数,类选择器个数,标签选择器个数)
然后两个选择器通过对别四个数字的大小,确定权重关系。
例:
#box ul li a.cur有1个id标签,1个类,3个标签,那么4个0就是(0,1,1,3)
.nav ul .active .cur有0个id,3个类,1个标签,那么4个0就是(0,0,3,1)
例:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        .p1{
            color: blue;
        }
        #p1{
            color: red;
        }
    </style>
</head>
<body>
            <p id="p1" class="p1">我们来试一下优先级</p>
</body>
</html>


先推测一波,因为前面讲到了ID选择器的权重是大于类选择器的,所以这里颜色应该为red。
效果如下:

推测正确!优先级GET!


vue,vant,使用过程中 Swipe 轮播自定义大小遇到的坑

前端达人

今天讲一下使用vant Swipe 轮播控件过程中遇到的问题

主要是使用swiper自定义的大小的时候,宽度适应不同分辨率的移动设备

适应宽度的同时还需控件的正常使用


先看一下需要实现的功能,

微信截图_20200417142351.png

微信截图_20200417142429.png

一个简单的轮播图,但是每个轮播的宽度需要低于100%,使第二个轮播的van-swipe-item可以展示到第一个位置一部分



这时我们再去vant的文档查看一下控件

微信截图_20200417142821.png


刚好有一个自定义控件大小的可以使用,完美解决了我们的问题


当我们使用控件之后


 <van-swipe :loop="false"  @change="onChange" :width="350">
        <van-swipe-item v-bind:id="item0"><div class="swipe0">
            <div class="contion">

                <p class="title">家中有事,申请请假一天</p>
                <p class="title1"><span class="rice"></span>部门经理核审中</p>
                <p class="time">03.8 &nbsp;&nbsp;&nbsp; 14.25</p>
                <p class="type">放假申请</p>
            </div>
            <img src="../../assets/images/index/xx/fangjia.png">

        </div></van-swipe-item>
        <van-swipe-item ><div class="swipe1"></div></van-swipe-item>
        <van-swipe-item ><div class="swipe2"></div></van-swipe-item>
        <template #indicator>
            <div class="custom-indicator">
                {{ current + 1 }}/3
            </div>
        </template>
    </van-swipe>



发现功能可以使用,但是再 iPhone8/7 plus  以及iPhone5/se 等分辨率下出现了宽度固定而不适应的情况,

微信截图_20200417143329.png

微信截图_20200417143349.png


简单来说,我们把van-swipe-item宽度控制在了80% 第二个van-swipe-item自然可以展示出来一部分

但是当滑到第二页的时候 由于第一页的宽度还是80% 所以就出现了这样的情况,所以我打算采用

监听 change 事件

动态的改变 滑动到第几页的时候 把当页的宽度变为80% 其他页保持不变,


于是

 <van-swipe :loop="false"  @change="onChange" >
        <van-swipe-item v-bind:id="item0"><div class="swipe0">
            <div class="contion">

                <p class="title">家中有事,申请请假一天</p>
                <p class="title1"><span class="rice"></span>部门经理核审中</p>
                <p class="time">03.8 &nbsp;&nbsp;&nbsp; 14.25</p>
                <p class="type">放假申请</p>
            </div>
            <img src="../../assets/images/index/xx/fangjia.png">

        </div></van-swipe-item>
        <van-swipe-item v-bind:id="item1"><div class="swipe1"></div></van-swipe-item>
        <van-swipe-item v-bind:id="item2"><div class="swipe2"></div></van-swipe-item>
        <template #indicator>
            <div class="custom-indicator">
                {{ current + 1 }}/3
            </div>
        </template>
    </van-swipe>





首先 我们为每个swipe-item添加id



 data(){
            return {
                android: true,
                ios: true,
                iphoneX: true,
                current: 0,
                item0:'item0',
                item1:'item1',
                item2:'item2',
            }
        },
        mounted(){

        },
        methods: {
            onChange(index){
                console.log('当前 Swipe 索引:' + index);
                if(index==1){
                    var div =document.getElementById("item0").style.setProperty('width', '10rem', 'important');
                    var div1 =document.getElementById("item1").style.setProperty('width', '9.3333333rem', 'important');
                    var div2 =document.getElementById("item2").style.setProperty('width', '9.3333333rem', 'important');
                } else  if(index==2){
                    var div1 =document.getElementById("item1").style.setProperty('width', '10rem', 'important');
                    var div0 =document.getElementById("item0").style.setProperty('width', '10rem', 'important');
                    var div2 =document.getElementById("item2").style.setProperty('width', '9.3333333rem', 'important');
                } else  if(index==0){
                    var div =document.getElementById("item2");
                    var div0 =document.getElementById("item0").style.setProperty('width', '9.3333333rem', 'important');
                    var div1 =document.getElementById("item1").style.setProperty('width', '9.3333333rem', 'important');
                }
            },



此外,监听滑动事件,根据滑动到第几页 更改当前页面的宽度,


这样就解决了




Swipe自定义宽度下,同时适应不同分辨率的情况


兰兰设计:前端达人





jquery,ajax请求并处理跨域

前端达人

自己写了段jquery的ajax请求,并输出到页面的表格中



<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>jQuery实现JSONP</title>
</head>
<body>
<div id="mydiv">
    <button id="btn">点击</button>

    <div id="container">
        <!--每个条目-->
        <div class="item">
            <div class="item-title">作业名字</div>
            <div>
                <span class="item-content">创建时间</span>
                <span class="item-content">发布老师</span>
            </div>
        </div>
    </div>
</div>
</body>
<script type="text/javascript" src="https://code.jquery.com/jquery-3.1.0.min.js"></script>
<script type="text/javascript">
    $(function(){
        $("#btn").click(function(){

            $.ajax({
                async : true,
                url : "xxxxxxxxxxx",
                type : "GET",
                dataType : "json", // 返回的数据类型,设置为JSONP方式
                jsonp : 'callback', //指定一个查询参数名称来覆盖默认的 jsonp 回调参数名 callback
                jsonpCallback: 'handleResponse', //设置回调函数名
                data : {
                    q : "javascript",
                    count : 1,
                    city:'北京'
                },
                success: function(response, status, xhr){
                    // console.log('状态为:' + status + ',状态是:' + xhr.statusText);
                    // console.log(response);

                    var group = response.hourly_forecast;

                    console.log(group,111111111)
                    console.log(group.length,222222222222)

                    //拼接字符串
                    var str = '';
                    //对数据做遍历,拼接到页面显示
                    for(var i=0;i<group.length;i++){
                        str += '<div class="item">'+
                                '<div class="item-title">'+ group[i].date +'</div>'+
                                '<div>'+
                                '<span class="item-content">'+ group[i].hum +'</span>'+
                                '<span class="item-content">'+ group[i].pop +'</span>'+
                                '</div>'+
                                '</div>';
                    }
                    //放入页面的容器显示
                    $('#container').html(str);

                }
            });
        });
    });

    function handleResponse(response){
        // 对response数据进行操作代码
        alert("jsonp success!");
    }
</script>
</html>


jquery中ajax处理跨域的三大方式


一、处理跨域的方式:

1.代理

2.XHR2

HTML5中提供的XMLHTTPREQUEST Level2(及XHR2)已经实现了跨域访问。但ie10以下不支持

只需要在服务端填上响应头:

header("Access-Control-Allow-Origin:*");

/*星号表示所有的域都可以接受,*/

header("Access-Control-Allow-Methods:GET,POST");

        

3.jsonP

原理:

 ajax本身是不可以跨域的, 通过产生一个script标签来实现跨域。因为script标签的src属性是没有跨域的限制的。

其实设置了dataType: 'jsonp'后,$.ajax方法就和ajax XmlHttpRequest没什么关系了,取而代之的则是JSONP协议。JSONP是一个非官方的协议,它允许在服务器端集成Script tags返回至客户端,通过javascript callback的形式实现跨域访问。

 ajax的跨域写法:

(其余写法和不跨域的一样):

比如 


GitHub如何配置SSH Key

前端达人

文章目录

    • 步骤


    • https://github.com/xiangshuo1992/preload.git
      git@github.com:xiangshuo1992/preload.git
      这两个地址展示的是同一个项目,但是这两个地址之间有什么联系呢?
      前者是https url 直接有效网址打开,但是用户每次通过git提交的时候都要输入用户名和密码,有没有简单的一点的办法,一次配置,永久使用呢?当然,所以有了第二种地址,也就是SSH URL,那如何配置就是本文要分享的内容。
      GitHub配置SSH Key的目的是为了帮助我们在通过git提交代码是,不需要繁琐的验证过程,简化操作流程。
      
      步骤
              

      一、设置git的user name和email

      如果你是第一次使用,或者还没有配置过的话需要操作一下命令,自行替换相应字段。
      git config --global user.name "Luke.Deng"
      git config --global user.email  "xiangshuo1992@gmail.com"
            
              

      二、检查是否存在SSH Key

      cd ~/.ssh
      ls
      或者
      ll
      //看是否存在 id_rsa 和 id_rsa.pub文件,如果存在,说明已经有SSH Key
      如果没有SSH Key,则需要先生成一下
      
      
      ssh-keygen -t rsa -C "xiangshuo1992@gmail.com"
            
              

      三、获取SSH Key

      cat id_rsa.pub
      //拷贝秘钥 ssh-rsa开头
            
              

      四、GitHub添加SSH Key

      GitHub点击用户头像,选择setting
       
      新建一个SSH Key 
      取个名字,把之前拷贝的秘钥复制进去,添加就好啦。
            
              

      五、验证和修改

      测试是否成功配置SSH Key
      
      
      ssh -T git@github.com
      //运行结果出现类似如下
      Hi xiangshuo1992! You've successfully authenticated, but GitHub does not provide shell access.
      之前已经是https的链接,现在想要用SSH提交怎么办?
      直接修改项目目录下 .git文件夹下的config文件,将地址修改一下就好了。
            
              


      ———————————————— 版权声明:本文为CSDN博主「前端向朔」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/u013778905/java/article/details/83501204



你真的了解重排和重绘吗?

前端达人

做过前端开发的小伙伴就算不是非常理解重排与重绘,但是肯定都听过这两个词。那为什么这两个东西这么重要?因为他与我们的页面性能息息相关,今天,我们就来好好研究一下这两个东西。



浏览器的渲染流程

在讲解重排和重绘之前,我们有必要说一下浏览器的渲染流程。下面是浏览器渲染过程中最关键的几个部分。如果想了解完整的浏览器渲染流程,推荐大家去阅读李兵老师的浏览器工作原理实践,需要付费阅读。后期我也会整理一下再出一篇博客详细介绍浏览器的渲染过程。


点击查看原图


JavaScript:一般来说,我们会使用 JavaScript 来实现一些视觉变化的效果。比如用 jQuery 的 animate 函数做一个动画、对一个数据集进行排序或者往页面里添加一些 DOM 元素等。当然,除了 JavaScript,还有其他一些常用方法也可以实现视觉变化效果,比如:CSS Animations、Transitions 和 Web Animation API。
样式计算:此过程是根据匹配选择器(例如 .headline 或 .nav > .nav__item)计算出哪些元素应用哪些 CSS 规则的过程。从中知道规则之后,将应用规则并计算每个元素的最终样式。
布局:在知道对一个元素应用哪些规则之后,浏览器即可开始计算它要占据的空间大小及其在屏幕的位置。网页的布局模式意味着一个元素可能影响其他元素,例如 元素的宽度一般会影响其子元素的宽度以及树中各处的节点,因此对于浏览器来说,布局过程是经常发生的。
绘制:绘制是填充像素的过程。它涉及绘出文本、颜色、图像、边框和阴影,基本上包括元素的每个可视部分。绘制一般是在多个表面(通常称为层)上完成的。
合成:由于页面的各部分可能被绘制到多层,由此它们需要按正确顺序绘制到屏幕上,以便正确渲染页面。对于与另一元素重叠的元素来说,这点特别重要,因为一个错误可能使一个元素错误地出现在另一个元素的上层。
其中,重排和重绘影响的就是其中的布局和绘制过程。

什么是重排和重绘制
重排:当DOM的变化引发了元素几何属性的变化,比如改变元素的宽高,元素的位置,导致浏览器不得不重新计算元素的几何属性,并重新构建渲染树,这个过程称为“重排”。
重绘:完成重排后,要将重新构建的渲染树渲染到屏幕上,这个过程就是“重绘”。
简单来说,涉及元素的几何更新时,叫重排。而只涉及样式更新而不涉及几何更新时,叫重绘。对于两者来说,重排必定引起重绘,但是重绘并不一定引起重排。所以,当涉及重排时,浏览器会将上述的步骤再次执行一遍。当只涉及重绘时,浏览器会跳过Layout步骤,即:


点击查看原图


而如果既不需要重排,也不需要重绘,那么就是下面这样:


点击查看原图



浏览器会直接跳到合成阶段。显然,对于页面性能来说,不重排也不重绘 > 重绘 > 重排。

什么操作会引起重排和重绘
显然,触发重排的一般都是几何因素,这是比较好理解的:

页面第一次渲染 在页面发生首次渲染的时候,所有组件都要进行首次布局,这是开销最大的一次重排
浏览器窗口尺寸改变
元素位置和尺寸发生改变的时候
新增和删除可见元素
内容发生改变(文字数量或图片大小等等)
元素字体大小变化
还有其他一些操作也可能引发重排

查询某些属性或调用某些方法
offset(Top|Left|Width|Height)
scroll(Top|Left|Width|Height)
client(Top|Left|Width|Height)
getComputedStyle()
我们可能不太理解为什么这些操作也能引起重排,这里我先简单解释一下。因为现在的浏览器已经非常完善了,会自动帮我们做一些优化。当我们用js操作DOM的时候,浏览器并不是立马执行的,而是将操作存储在一个队列中。当达到一定数量或者经过一定时间以后浏览器再统一的去执行队列中的操作。那么回到我们刚才的问题,为什么查询这些属性也会导致重排?因为当你查询这些属性时,浏览器就会强制刷新队列,因为如果不立马执行队列中的操作,有可能得到的结果就是错误的。所以相当于你强制打断了浏览器的优化流程,引发了重排。下面我们通过一些小例子来进一步理解这段话:

首先我们来一个显然会引发重排的操作

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    #test {
      width: 100px;
      height: 100px;
      background-color: red;
      position: relative;
    }
  </style>
</head>
<body>
  <div id="test">

  </div>
  <button onclick="reflow()">click</button>
  <script>
    function reflow() {
      var div = document.querySelector("#test");
      div.style.left = '200px';
    }
  </script>
</body>
</html>



把时间轴往后拉,可以看到这几个过程,先简单介绍一些这些名词代表的含义:

Recalculate Style:这个过程就是生成CSSOM的过程
Layout:这就是布局阶段,即重排的过程
Update Layer Tree:这个阶段是更新层树的过程
Paint:该阶段是为每一层准备绘制列表的过程
Composite Layers:该阶段是利用绘制列表来生成相应图层的位图了,还涉及到合成线程和光栅化,performence面板中的Raster就是光栅化线程池 。
这里只做一个简单的介绍,对其中内容不太明白的同学可以参考李兵老师的文章或者在我的下一篇介绍浏览器渲染过程的文章中会详细解释。

那通过这个图我们可以看到,我们改变了div的left之后就触发了Layout,即重排的过程。下面我们仅改变div的背景颜色,给大家一个对比。


即不重排也不重绘
说完了重排和重绘,不要忘记我们最开始提到的,最的方式就是跳过重排和重绘阶段。你可能会想,什么情况下可以做到这一点?其实这就是我们平时说的GPU加速,具体是如何实现呢?在开发过程中,如果我们使用了某些属性,浏览器会帮助我们将使用了该属性的div提升到一个单独的合成层,而在后面的渲染中,提升到该层的div将跳过重排和重绘的操作,直接到合成阶段。在stack overflow上有问题提到了这块内容。我们翻译一下就是:
下面几个属性能让浏览器帮助我们将div提升到一个单独的合成层:

图层具有3D或透视变换CSS属性
使用加速视频解码的 video 元素
拥有 3D(WebGL) 上下文或者加速 2D 上下文的 canvas 元素
混合插件(Flash)
对自己的 opacity 做 CSS 动画或使用一个动画 webkit 变换的元素
图层使用加速的CSS过滤器
层具有作为合成层的后代
图层具有较低z索引的同级元素,该同级元素具有合成层(换句话说,该层在合成层的顶部渲染)
css will-change属性
最后一点是我加上去的,同时根据文中的内容我们可以知道,css3硬件加速是浏览器的行为,所以在不同浏览器下可能会有不同的表现形式。下面我们用一个例子来理解一下。这是李兵老师在他的专栏中提出的一个例子,我拿过来借用一下,注意box中的will-change属性:

<html>

  <head>
      <title>观察will-change</title>
      <style>
          .box {
              will-change: transform, opacity;
              display: block;
              float: left;
              width: 40px;
              height: 40px;
              margin: 15px;
              padding: 10px;
              border: 1px solid rgb(136, 136, 136);
              background: rgb(187, 177, 37);
              border-radius: 30px;
              transition: border-radius 1s ease-out;
          }

          body {
              font-family: Arial;
          }
      </style>
  </head>

  <body>
      <div id="controls">
          <button id="start">start</button>
          <button id="stop">stop</button>
      </div>
      <div>
          <div class="box">旋转盒子</div>
          <div class="box">旋转盒子</div>
          <div class="box">旋转盒子</div>
          <div class="box">旋转盒子</div>
          <div class="box">旋转盒子</div>
          <div class="box">旋转盒子</div>
          <div class="box">旋转盒子</div>
          <div class="box">旋转盒子</div>
          <div class="box">旋转盒子</div>
          <div class="box">旋转盒子</div>
          <div class="box">旋转盒子</div>
          <div class="box">旋转盒子</div>
          <div class="box">旋转盒子</div>
          <div class="box">旋转盒子</div>
          <div class="box">旋转盒子</div>
          <div class="box">旋转盒子</div>
          <div class="box">旋转盒子</div>
          <div class="box">旋转盒子</div>
          <div class="box">旋转盒子</div>
          <div class="box">旋转盒子</div>
          <div class="box">旋转盒子</div>
          <div class="box">旋转盒子</div>
          <div class="box">旋转盒子</div>
          <div class="box">旋转盒子</div>
          <div class="box">旋转盒子</div>
          <div class="box">旋转盒子</div>
          <div class="box">旋转盒子</div>
          <div class="box">旋转盒子</div>
          <div class="box">旋转盒子</div>
          <div class="box">旋转盒子</div>
          <div class="box">旋转盒子</div>
          <div class="box">旋转盒子</div>
          <div class="box">旋转盒子</div>
          <div class="box">旋转盒子</div>
          <div class="box">旋转盒子</div>
          <div class="box">旋转盒子</div>
          <div class="box">旋转盒子</div>
          <div class="box">旋转盒子</div>
          <div class="box">旋转盒子</div>
          <div class="box">旋转盒子</div>
          <div class="box">旋转盒子</div>
          <div class="box">旋转盒子</div>
          <div class="box">旋转盒子</div>
          <div class="box">旋转盒子</div>
          <div class="box">旋转盒子</div>
          <div class="box">旋转盒子</div>
          <div class="box">旋转盒子</div>
          <div class="box">旋转盒子</div>
          <div class="box">旋转盒子</div>
          <div class="box">旋转盒子</div>
          <div class="box">旋转盒子</div>
          <div class="box">旋转盒子</div>
          <div class="box">旋转盒子</div>
          <div class="box">旋转盒子</div>
          <div class="box">旋转盒子</div>
          <div class="box">旋转盒子</div>
          <div class="box">旋转盒子</div>
          <div class="box">旋转盒子</div>
          <div class="box">旋转盒子</div>
          <div class="box">旋转盒子</div>
      </div>
      <script>

          let boxes = document.querySelectorAll('.box');
          let boxes1 = document.querySelectorAll('.box1');
          let start = document.getElementById('start');
          let stop = document.getElementById('stop');
          let stop_flag = false

          start.addEventListener('click', function () {
              stop_flag = false
              requestAnimationFrame(render);
          })

          stop.addEventListener('click', function () {
              stop_flag = true
          })

          let rotate_ = 0
          let opacity_ = 0
          function render() {
              if (stop_flag)
                  return 0
              rotate_ = rotate_ + 6
              if (opacity_ > 1)
                  opacity_ = 0
              opacity_ = opacity_ + 0.01
              let command = 'rotate(' + rotate_ + 'deg)';
              for (let index = 0; index < boxes.length; index++) {
                  boxes[index].style.transform = command
                  boxes[index].style.opacity = opacity_
              }
              requestAnimationFrame(render);
          }
      </script>
  </body>

  </html>



————————————————
版权声明:本文为CSDN博主「溪宁」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_38164763/article/details/105406580

【CSS基础学习】复杂选择器

前端达人

文章目录

    • CSS第二课-复杂选择器
      • 群组选择器
      • 属性选择器
      • 派生选择器
      • CSS第二课-复杂选择器

        群组选择器

        格式

        选择器1,选择器2,,,选择器n{声明的属性和属性值}

        p,h1{
            color: blue;
        }


        用于对于多个选择器进行样式修改,由简单选择器组合而成的选择器,可以是简单选择器中的任意组合,如上面代码例,就是修改了p标签和h1标签的字体颜色。

        属性选择器

        根据属性名查找元素

        格式

        元素[属性名]{
            声明的属性和属性值;
        }


        p[id]{
            color: blue;
        }


        前面添加元素的名字,然后后面加上属性名,比如上例,就是p标签,其中带有id的元素,然后把字体颜色设置为蓝色。

        根据属性值查找

        格式

        元素[属性名=属性值]{
            声明的属性和属性值;
        }


        p[class = 'p2']{
            color: blue;
        }


        和上面的根据属性名查找差不多,只不过更加了,到了属性名后面的属性值,上例就是作用于p标签,只不过条件是为带有class属性,并且属性值为p2的p标签。

        多属性选择器

        格式


        元素[属性名或属性表达式][属性名或属性表达式]..{
            声明的属性和属性值;
        }
        p[title][class]{
            color: blue;
        }



        元素后面加。属性名或属性表达式,可以加+∞个,但是没必要。上例为:设置title属性和class属性的段落p标签的样式

        根据属性值近似查找

        格式


        元素[元素名~=属性值]{
            声明的属性和属性值;
        }


        元素[属性名|=值]{
            声名的属性和属性值;
        }


        p[class~='red']{
            color: blue;
        }



        注意,这里是~=,为约等于,就是找满足符合约等于条件的标签,上例为:设置class属性的值,包含red属性名的标签

        根据标签查找

        格式


        元素名1~元素名2{
            声名的属性和属性值;
        }


        a~p{
            color: blue;
        }


        a标签后面的每一个p标签,都进行了样式的修改。

        派生选择器

        后代选择器

        格式


        父类标签 子类标签{ /*注意俩标签中间有空格*/
            声名的属性和属性值;
        }


        div strong{
            color: blue;
        }


        相邻兄弟选择器

        格式


        父标签+子标签{
            声名的属性和属性值;
        }


        #div1 + p{
            color: blue;
        }


        相邻兄弟选择器可选择紧接在另一个元素后的元素,且二者具有相同的父亲元素。注释:与子结合符一样,相邻兄弟结合符旁边可以有空白符。




        ————————————————
        版权声明:本文为CSDN博主「董小宇」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
        原文链接:https://blog.csdn.net/lolly1023/article/details/105413125

JavaScript 的简述与基础语法

前端达人

目录

JavaScript

  1. JS 发展历史
  2. JS 的特点
  3. JS 的组成
  4. JS 的基础语法

    a. 两种引入方式 type src

    b. 三种输出方式 console.log document.write alert

    c. 变量声明 var let const typeof undefined

    d. 数据类型简介 string number boolean object undefined

    e. 运算符 + - * / % = < > && || !

    i. 全等符与不全等符 === !==

    f. 流程控制语句

    i. 条件语句 if else switch case default break

    ii. 循环语句 while dowhile fori forin forof



    JavaScript

    • JS 用于完成页面与用户的交互功能;

    1. JS 发展历史
    JavaScript 在 1995 年由 Netscape 公司的 Brendan Eich,在网景导航者浏览器上首次设计实现而成。因为 Netscape 与 Sun 合作,Netscape 管理层希望它外观看起来像 Java,因此取名为 JavaScript。但实际上它的语法风格与 Self 及 Scheme 较为接近;
    欧洲计算机制造联盟(ECMA)在 1997 制定脚本语言规范 ECMA Script1 (ES1),2009 年发布了 ECMA Script5(ES5),在 2015 年发布了 ECMA Script 2015(ES6),所有的浏览器的都支持 ES6;

  5. JS 的特点

    JS 设计模仿了 Java 语言,不同如下:

    JS 不需要编译,由浏览器直接解释执行;

    JS 是弱类型语言,JS 变量声明不需要指明类型,不同类型的数据可以赋值给同一变量;
  6. JS 的组成

    ECMA Script 是 JS 的基础语法;

    BOM(Brower Object Model)是浏览器对象模型;

    DOM(Document Object Model)是文档对象模型;
  7. JS 的基础语法

    a. 两种引入方式 type src




    <!DOCTYPE html>
    <html lang="zh">
    <head>
    <meta charset="UTF-8">
    <title>JS两种引入方式</title>
    </head>
    <body>
    <!-- JS两种引入方式:JS和CSS一样都需要引入到html页面中,浏览器才会解释执行,JS有两种引入方式:
        1.内嵌(内部)脚本:在script标签中写js代码,script标签推荐放置在body标签的底部,理论上和style标签一样可以放置位置任意;
        2.外部脚步:使用script标签的src属性引入外部js文件,使用注意事项: script标签使用了src属性以后内部的代码不再被浏览器解释执行,script引入外部脚本时不能使用自闭合格式 -->
    <!--告诉浏览器把解析器切换为js解析器 type="text/javascript"可以省略-->
    <script type="text/javascript"> document.write("<h1>内部脚本</h1>");//向body中追加html内容 </script>
    <script src="../js/外部脚本.js"></script>
    </body>
    </html>
    






    b. 三种输出方式 console.log document.write alert

    <!DOCTYPE html>
    <html lang="zh">
    <head>
    <meta charset="UTF-8">
    <title>JS三种输出方式</title>
    </head>
    <body>
    <!-- JS三种输出方式:
        1.输出到浏览器控制台;
        2.输出html内容到页面;
        3.浏览器弹框输出字符 -->
    <script>
    //1.输出到浏览器控制台
    console.log("1. 输出到浏览器控制台");//开发者专用
    //2.输出html内容到页面
    document.write("2. 输出html内容到页面");//向body中追加html内容
    //3.浏览器弹框输出字符
    alert("3. 浏览器弹框输出字符");//阻塞执行
    </script>
    </body>
    </html>
    


    c. 变量声明 var let const typeof undefined


    <!DOCTYPE html>
    <html lang="zh">
    <head>
    <meta charset="UTF-8">
    <title>JS变量</title>
    </head>
    <body>
    <!-- JS变量用来存放数据;
        es5以前变量声明使用var;
        es6之后变量声明使用let,常量声明使用const。他们用于替代es6的var声明方式;
     JS是弱类型语言: 
        声明变量时不知道变量的类型(undefined),只有在赋值之后js变量才确定类型;
        typeof(a) 或 typeof a 输出变量的类型;
        undefined表示变量未赋值,未知类型 -->
    <script>
    //字符串 Java声明 String str ="张三";
    let str ="张三";
    console.log(str);
    //整数 Java声明 int k = 5;
    let k = 5;
    console.log(k);
    //小数 Java声明 float f = 7.5;
    let f = 7.5;
    console.log(f);
    //常量 Java声明 final Integer PI = 3.14;
    const PI = 3.14;
    console.log(PI);
    //演示弱类型语言
    let a;//声明变量不需要指明类型
    console.log(typeof a);//undefined 未赋值类型,未知类型
    a = "你好";
    console.log(typeof a);//string
    a = 123;
    console.log(typeof a);//number
    a = true;
    console.log(typeof a);//boolean
    a = new Object();
    console.log(typeof a);//object
    </script>
    </body>
    </html>
    


    d. 数据类型简介 string number boolean object undefined


    <!DOCTYPE html>
    <html lang="zh">
    <head>
    <meta charset="UTF-8">
    <title>JS数据类型</title>
    </head>
    <body>
    <!-- JS数据类型,常用数据类型:
        1.string 字符串类型;
        2.number 数字.包括整数和小数类型;
        3.boolean 布尔类型.值只有true和false两个;
        4 object 对象类型,空对象使用null表示,有两种格式:
            new Object(); 
            JSON格式.例如:{name:"张三",age:18};
        5.undefined 变量未赋值 -->
    <script>
    //1. string 字符串
    let str = "你好";
    console.log(str);
    console.log(typeof str);//string
    // 2. number 数字
    let n = 123.456;
    console.log(n);
    console.log(typeof n);//number
    // 3. boolean 布尔类型
    let boo = false;
    console.log(boo);
    console.log(typeof boo);//boolean
    // 4. object 对象类型,空对象使用 null表示
    let obj = null;//或 new Object();
    console.log(obj);
    console.log(typeof obj);//object
    // 5. undefined 变量未赋值
    let u = undefined;
    console.log(u);//值是undefined
    console.log(typeof u);//类型是undefined
    // Object类型
    let stu = new Object();//创建一个js对象,js对象的属性想要直接加上
    stu.id = 1;
    stu.name = "刘一";
    stu.age = 18;
    console.log(stu);//{id: 1, name: "刘一", age: 18}
    console.log(typeof stu);//object
    // JS对象取属性值有两种方式:
    // 1. obj.key
    console.log(stu.name);//刘一
    // 2. obj["key"]
    console.log(stu["name"]); //刘一 == stu.name
    let b = "age";
    console.log(stu[b]);//可以取不定属性的值
    </script>
    </body>
    </html>
    


    e. 运算符 + - * / % = < > && || !


    i. 全等符与不全等符 === !==


    <!DOCTYPE html>
    <html lang="zh">
    <head>
    <meta charset="UTF-8">
       <title>JS运算符</title>
    </head>
    <body>
    <!--
    JS运算符
    js运算符和Java运算符基本相同
    只有一个特殊的比较运算符
    === 判断js变量的值和类型都相等才为true
    !== 不全等,判断js变量的值和类型有一个不等就为true
    -->
    <script> let a = 3;
    let b = "3";
    console.log(a == b);//true
    // 全等 运算符 ===
    console.log(a === b);//false
    // 不全等 运算符 !==
    console.log(a !== b);//true
    // 三元(三目)运算符 布尔表达式?真:假
    let str = a===b?"全等":"不全等";
    console.log(str);//不全等
    </script>
    </body>
    </html>
    


    f. 流程控制语句

    i. 条件语句 if else switch case default break


    <!DOCTYPE html>
    <html lang="zh">
    <head>
    <meta charset="UTF-8">
    <title>条件语句</title>
    </head>
    <body>
    <!-- 条件语句JS的条件语句和Java语法基本一样,但是对数据类型的真假判断有些区别 JS中对各种数据类型作为布尔值的特点:(重点掌握) 1. string 空字符串""为false,其余都为true 2. number 数字 只有0为false,其余数字都为true 3. boolean 布尔类型 值只有 true和false 两个
    循环语句
  8. object 对象类型 空对象null表示false,其它对象都是true 5. undefined 变量未赋值 为false 常用语法格式 if ... else if ... else switch case break default -->
    <script>
    //if ... else
    //if(true){
    //if(""){// string 只有空字符为假
    //if(0){number 只有0为假
    //if(false){//boolean false为假 true为真
    //if(null){//object null为假
    //if(undefined){//undefined永为假
    if("undefined"){//undefined永为假
    console.log("满足条件");
    }else{
    console.log("不满足条件");
    }

    //switch case break default
    let k =1;
    switch (k) {
    case 1:
    console.log("111");break;
    case 2:
    console.log("222");break;
    default: console.log("其它情况"); }
    </script>
    </body>
    </html>


    ii. 循环语句 while dowhile fori forin forof


    <!DOCTYPE html>
    <html lang="zh">
    <head>
    <meta charset="UTF-8">
    <title>循环语句</title>
    </head>
    <body>
    <!-- 循环语句
        while,do while,fori 和Java一样;
        forin
            1.遍历出数组中的索引和元素
            2.遍历出对象中的属性和元素
        forof 
            1.遍历出数组中的元素
        forin 与 forof 区别:
            1.forin可以遍历对象,forof不能遍历对象
            2.forin可以遍历出数组中的索引,forof只能遍历出数组中的元素 -->
    <script>
    //while 和Java一样
    let k=1;
    while (k<3){
        console.log(k++);
    }
    
    //do while 和Java一样
    k =1;
    do{
        console.log(k++);
    }while (k<3)
    
    //fori 和Java一样
    for(let i=0;i<3;i++){
        console.log(i);
    }
    
    //forin 可以遍历数组和对象
    let arr = ["刘一","陈二","张三"];//JS数组使用中括号[]定义
    let stu = {id:5,name:"李四",age:18};//JS对象使用大括号定义
        //1.forin 遍历出数组中的索引
    for(let index in arr){
        console.log(index);//数组的索引 0,1,2
        console.log(arr[index]);//数组中的元素
    }
        //2.forin 遍历出对象中的属性名key
    for(let k in stu){
        console.log(k);//字符串属性 id,name,age
        console.log(stu[k]);//对象中的属性值
    }
    
    //forof 可以遍历数组
    for(let e of arr){
        console.log(e);//数组中的元素
    }</script>
    </body>
    </html>
    
    
    
    
    
    ————————————————
    版权声明:本文为CSDN博主「Regino」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
    原文链接:https://blog.csdn.net/Regino/article/details/105321573
    

原文链接:https://blog.csdn.net/Regino/article/details/105321573 





日历

链接

个人资料

蓝蓝设计的小编 http://www.lanlanwork.com

存档