前端知识小结

1、html5中的新特性
    语义化标签:article、footer、header、nav、section...
    表单控件:date、time、email、url、search(input框type的取值)
    音视频:video、audio
    画布:canvas
    本地离线存储:localStorage

2、css3新增属性
    边框:border-radius【边框圆角】、box-shadow【边框阴影】
    背景:background-size【背景图片的尺寸】
        background-size:100% 100%;
    文本:text-shadow【文本阴影】
        text-shadow: 5px 5px 5px yellow; [水平距离、垂直距离、模糊距离、颜色]
    变换:transfrom
    过渡:transition
    动画:animation
        设置关键帧
            @keyframes animate {
              0%{
                  margin-left:0px;
              }
              50%{
                  margin-left:10px;
              }
              100%{
                  margin-left:20px;
              }
            }
        使用动画
            div{
                animation:animate 3s infinite;
            }
            ===>
            animation-name:animate; 【动画名称】
            animation-duration:3s; 【动画时间】
            animation-iteration-count:infinite; 【动画次数】
            animation-direction 【动画方向】

        IE9之前的版本不支持动画

3、清除浮动的方式
    什么是浮动?
        元素使用了float:left/right;后,会脱离文档流,父元素因此会失去支撑(如果父元素中没有其他元素,并且没有设置宽高),下面的元素就会紧贴着父元素上方的元素开始布局
    常用方式:
        1) 浮动元素的父元素
            overflow:hidden;
        2) 浮动元素的父元素
            .parent::after{
                clear:both;
                content:'';
                display:block;
            }
        3) 浮动元素的兄弟元素(同级元素)
            添加一个空标签,设置clear:both;

4、浮动与绝对定位脱离文档流的区别【脱离文档流的元素内的文本】
    float:left/right
        其他的盒子会无视当前的盒子,从页面的左上方开始布局,但是对于盒子内的文本,依旧会为浮动的元素让出空间
    绝对定位: 
        其他的盒子会无视当前的盒子,从页面的左上方开始布局,但是对于盒子内的文本,不会为浮动的元素让出空间
    参考:https://blog.csdn.net/qq_42720683/article/details/98513061

5、盒子模型
    盒子组成
        内容的width + padding + border + margin
    通过box-sizing可以设置不同的盒子模型
        box-sizing:content-box; 【默认值】  --  气球
            内容盒子(W3C标准盒子)
            盒子的总宽度 = margin + border + padding + width

        box-sizing:border-box;  --  铁盒子
            边框盒子(IE盒子)
            盒子的总宽度 = margin + width

    参考:https://blog.csdn.net/qq_42720683/article/details/83584970

6、块级元素与行内元素的区别
    块级元素
        div、h1~h5、p、html、body、ul、li...
        1) 独占一行
        2) 默认宽度为100%,默认的高度由内容决定
        3) 可以指定宽高

    行内元素        
        span、a、img、strong、i
        1) 不独占一行,与其他元素共享一行
        2) 默认宽高由内容决定
        3) 不能指定宽高
        4) 行内元素不可以嵌套块级元素,但是块级元素可以嵌套行内元素

7、如何给行内元素设置宽高? 将行内元素转换为块级元素、脱离文档流
    1) 使用display
        display:block/inline-block
    2) 使用position
        position:absolute/fixed
    3) 使用float
        float:left/right

8、块级元素如何在父元素中水平垂直居中?
    1) 父元素position
        1. 
            父元素position:relative;
            子元素
                position:absolute;
                margin:auto;
                top:0;
                right:0;
                bottom:0;
                left:0;
        2. 
            父元素position:relative;
            子元素
                position:absolute;
                left:50%;
                top:50%;
                margin-left:-子元素宽度的一半;
                margin-top:-子元素高度的一半;                

    2) 父元素display
        *3. 
            父元素
                display:flex;
                justify-content: center;
                align-items: center;
            子元素
                自动水平垂直居中
        4. 
            父元素
                display:table-cell;
                vertical-align: middle;
            子元素
                display:inline-block;

    参考:https://blog.csdn.net/qq_42720683/article/details/83348894

9、元素隐藏的方式及其区别
    display:none;   浏览器不显示元素,也不占据页面空间
    opacity:0;  浏览器不显示元素,但是会占据页面空间,交互事件正常
    visibility:hidden; 浏览器不显示元素,但是会占据页面空间,交互事件失效
        <style>
            span{
                background-color: red;
                /* display: none; */
                /* opacity: 0; */
                visibility:hidden;
            }
        </style>
        <span id='one'>123</span>
        <script>
            var dom = document.getElementById('one')
            dom.onclick = function(){
                alert(1)
            }
        </script>

    注意:当父元素使用opacity改变透明度的时候,子元素也会改变透明度,即使子元素设置了opacity: 1;也无效
    解决方法:父元素使用rgba(0,0,0,0.4)

10、link和@import的区别
    1) 所属范围
        @import 是css的语法,只能导入样式
        link是html的标签,不仅可以加载样式,还可以定义rel属性
            rel="stylesheet"表示调用外部样式表
    2) 加载顺序
        页面加载的时候,link标签引入的css被同时加载
        @import引入的css在页面加载完毕后再被加载
    3) 兼容性
        @import需要兼容IE5+
        link标签,不存在兼容性问题

11、如何让一个元素使用margin:0 auto;水平居中
    margin:0 auto只对块级元素生效

    1) 块级元素【只用设置宽度】
        div {
            width:200px;
            margin:0 auto;
        }
    2) 行内元素【需要将行内元素设置为块级元素,再加宽度】
        span {
            display:block;
            width:200px;
            margin:0 auto;
        }
    3) 行内块元素(内联元素) button、input、textarea【需要将行内块元素设置为块级元素,可以不加宽度】
        input {
            display:block;
            margin:0 auto;
        }

12、overflow的三种取值及其含义
    使用前提:父元素需要设置一个高度,这样子元素超出给定的高度后,才能做如下操作
    auto    自适应,内容如果溢出,会自动生成滚动条
    scroll  将溢出的部分进行裁剪(也就是不显示),并以滚动条的形式显示超出的部分(如果不设置滚动条隐藏,滚动条一直存在)
    hidden  将溢出的部分进行裁剪,不会出现滚动条

13、js的数据类型
    1) 基本数据类型
        number、string、boolean、null、undefined
    2) 引用数据类型
        对象、数组、函数(可以统称为 对象)

14、变量的提升
    用来描述变量和函数移动到当前作用域的最顶部的术语
        全局作用域
        函数作用域
        块级作用域
    编译:编译阶段,js会获取到所有的函数声明、使用var关键字声明的变量,将其提升到作用域的顶部
    注意:
        1、只有使用var声明的变量、或者是函数声明才会被提升
        2、箭头函数、let和const声明的变量都不会发生变量的提升

15、null与undefined的区别
    undefined:变量声明但是未被初始化、访问对象中不存在的属性、函数没有显示的返回值
        let a = ()=>{}
        console.log(a())
    null代表没有任何值的值
    
    null == undefined // true
    null === undefined // false

16、== 与 === 的区别
    == 用于一般的比较,在比较的时候会自动进行数据类型的转换
    === 用于严格比较,不会进行数据类型的转化,只要两个变量的数据类型不一样,直接返回false

17、js数据类型的检测
    1) typeof
        语法:typeof A
        返回值:number、string、boolean、undefined、object、function
        结论:对于数组、对象、null检测的结果都是object

        对于基本数据类型来说,除了null其他的都可以正常的检测
        对于引用数据类型来说,除了函数都会显示成object

    2) instanceof
        含义:用于检测构造函数的prototype属性是否出现在某个实例对象的原型链上
        也就是判断A是否为B的实例
        语法:A instanceof B【如果A是B的实例,则返回true】
        返回值:true/false
            console.log(1 instanceof Number); // false
            console.log([] instanceof Array); // true
            console.log({} instanceof Object); // true
            console.log(function(){} instanceof Function); // true
        结论:无法判断基本数据类型,对于引用数据类型无法准确定位

    3) Array.isArray() 
        含义:检测一个变量是否是数组
        语法:Array.isArray(A)
        返回值:true/false
            console.log(Array.isArray([])); // true
            console.log(Array.isArray({})); // false
        结论:可以准确的检测数组
    
    4) Object.prototype.toString.call()
        含义:判断某个变量属于哪个内置的类型
        语法:Object.prototype.toString.call(A)
        返回值: [object Number] [object String]...
        结论:可以检测所有的数据类型

        js的内置数据类型:null、string、boolean、number、undefined、array、function、object、date、math

18、如何判断对象中是否存在某个属性?
    1) in操作符
        var obj = {
            name:'tom'
        }
        console.log('name' in obj); // true
        console.log('age' in obj); // false

    2) hasOwnProperty()
        var obj = {
            name:'tom'
        }
        console.log(obj.hasOwnProperty('name')); // true
        console.log(obj.hasOwnProperty('age')); // false

    in操作符可以检测到继承的属性,而hasOwnProperty不能

19、如何判断一个对象是空对象?
    1) 
        var obj = {}
        console.log(JSON.stringify(obj) == '{}')

    2) Object.keys()返回一个由给定对象的可枚举属性组成的数组
        var obj = {}
        console.log(Object.keys(obj).length == 0)

20、this指向
    如何判断this的指向:this的指向与该函数的调用方式有关
        函数名(实参)
        函数名.call(this,实参列表)
        函数名.apply(this,实参数组)
    1) 如果函数使用()直接调用,看函数名之前有没有对象
        有:this指向该对象【谁调用了该函数,this就指向谁】
        没有:全局对象
    2) 如果函数通过call、apply调用,this为用户手动指向的那个对象【更改this的指向】
    3) 箭头函数中的this指向该箭头函数外部函数的this

21、数组常用api
    push
    pop
    shift
    unshift
    sort排序
        比较器函数
        当a>b时返回1,从小到大排序
        当a<b时返回-1,从大到小排序
        var arr = [1,3,21,13,2]
        var res = arr.sort(function(a,b){
            if(a>b){
                return 1;
            } else {
                return -1;
            }
        })
    toString 将数组转换为字符串,通过逗号连接
    join(s) 将数组转换为字符串,通过s连接
    JSON.stringify 将数组转换为json字符串
    concat 合并数组
    slice 从数组中截取一个子数组
    splice 从数组中删除、插入元素
    forEach(function(item,index,arr){}) 遍历当前数组
        返回值:无
    every() 
        返回值:true/false
    some() 
        返回值:true/false
    filter()
        返回值:数组
    map() 【映射】
        返回值:一个处理后的数组

        注意:
            1. 不会改变原数组
            2. 对于空数组map方法不会检测

22、类数组对象转换为数组
    类数组对象的特征:【arguments】
        1. 具有索引
        2. 具有length属性
    方法:
        1) [...arguments]【前提:只对拥有遍历器对象的有效】
        2) Array.from(arguments)
        3) Array.prototype.slice.call(arguments)

23、正则表达式
    1) 正则表达式的定义
        var pattern = new RegExp('正则表达式','正则表达式修饰符')
        var pattern = /ab/img;

        正则表达式修饰符
            i   忽略大小写
            g   全局
            m   多行

    2) 正则表达式方法
        test()  检测正则表达式是否匹配某个字符串,如果匹配到返回true
        exec()  检测正则表达式是否匹配某个字符串,如果匹配到将该字符串返回到一个数组中
    
    3) 正则表达式
        .
        \d  [0-9]
        \D  [^0-9]
    
    4) 贪婪匹配与非贪婪匹配
        贪婪匹配    --      尽可能多的匹配
            /\D{2,}/
        非贪婪匹配  --      尽可能少的匹配
            /\D{2,}?/

24、包装器类型
    基本包装器  Number() String() Boolean() Math() Date()
    1) String.prototype.xxx
        length  字符串长度    
        indexOf()   字符首次出现时的索引
        concat()    连接字符串
        slice()     截取子字符串
        trim()      去除字符串两边空格
        match()     找出匹配的内容
        split()     将字符串分割为字符串数组
    2) Math
        Math.floor()    向下舍入
        Math.ceil()    向上舍入
        Math.round()    四舍五入
        Math.random()    随机数【0-1】
    3) Date
        var date = new Date();
        getFullYear()   年
        getMonth()      月
        getDay()        日
        getHours()      时
        getMinutes()    分
        getSeconds()    秒
        getTime()       时间戳

        补全位数
            .toString.padStart(2,'0')
    4) 日期格式转换
        1. 自己写
        2. moment
            var date = new Date();
            var res = moment(date).format('YYYY-MM-DD hh:mm:ss');
    
25、数组去重
    1) indexOf() 可返回数组中某个元素首次出现时的索引
    2) ES6的Set,Set集合中不存在重复的元素
    3) [...new Set(arr)]

26、高级面向对象
    1) 工厂函数模式
        function factory(){
            return {}
        }
        1. 类型无法区分
        2. 函数重复的创建

    2) 构造函数模式
        function Test(){}
        var test = new Test()
        
        1. 构造函数的执行过程
            1、创建新对象
            2、将当前构造函数的作用域赋值给新的对象【也就是this的指向】
            3、给新的对象添加属性和方法
            4、将新的对象返回

        2. 构造函数与普通函数的区别
            构造函数:function Test(){}
            普通函数:function test(){}

            1、构造函数的首字母大写【习惯上】,但是本质上也是一个普通函数
            2、调用方式
                普通函数:直接调用test()
                构造函数:使用new关键字调用,new Test()
            3、返回值
                普通函数:没有返回值
                构造函数:对象
        3. 问题:函数重复的创建
    
    3) 构造函数与原型结合
        属性保存在实例中,方法保存在构造函数的原型上
        function Dog(){name,age,gender}{
            this.name = name;
            this.age = age;
            this.gender = gender;
        }
        Dog.prototype.sayGender = function(){
            console.log('xxx')
        }

        var dog1 = new Dog();
        var dog2 = new Dog();
        dog1.sayGender()
        dog2.sayGender()

    4) 原型链继承 【子构造函数的原型指向父构造函数的实例】
        Person1
            function Person1(name){
                this.name = name;
            }
            Person1.prototype.money = function(){
                console.log('xx')
            }
            var per1 = new Person1('tom');
            per1.money();
        Person2
            function Person2(name){
                this.name = name;
            }
            var per2 = new Person2('larry');
            larry.money(); // 报错

        解决:【写在Person2构造函数创建的代码之上】
            Person2.prototype = new Person1()
            Person2.prototype.constructor = Person2;【解决分类问题】

    5) 借用构造函数【不仅仅可以继承方法,也可以继承属性】
        Person1.call(this,name,age)

            function Person1(name){
                this.name = name;
            }
            Person1.prototype.money = function(){
                console.log('xx')
            }
            var per1 = new Person1('tom');
            per1.money();

            Person2.prototype = new Person1()
            Person2.prototype.constructor = Person2;

            function Person2(name,age){
                Person1.call(this,name) 【将Person1中的this指向了Person2】
                this.age = age;
            }
            var per2 = new Person2('larry');
            larry.money(); // 报错

27、什么是DOM【文档对象模型】
    vue与jQuery的区别?
        vue零dom操作
        jQuery是依赖于dom操作的

28、节点操作
    1) 节点的创建
        var dom = document.createElement('标签名')
    2) 节点的追加
        1. parent.appendChild(dom)
        2. parent.insertBefore(dom,index) 
            dom -- 节点
            index --  位置
    3) 节点的复制【克隆】
        1. 浅复制
            cloneNode() / cloneNode(false)
            只复制标签,不复制内容
        2. 深复制
            cloneNode(true)
            复制标签及内容
    4) 节点的删除
        parent.removeChild(item)

29、事件三要素
    事件目标、事件处理程序、事件对象

30、事件冒泡和事件捕获的区别
    前提:
        1. 元素需要嵌套
        2. 每层元素上需要绑定相同类型的事件

    1) 事件流
        页面中元素接收事件的顺序

    2) 事件冒泡【由内向外】
        事件发生在具体的元素上,然后逐级向上传播到不具体的元素
        可以通过event.stopPropagation()阻止事件冒泡
            inner.onclick = function(){
                event.stopPropagation();
            }

    3) 事件捕获【由外向内】
        事件发生在不具体的元素上,然后逐级向下传播到具体的元素

31、event.stopPropagation()、event.preventDefault()、return false的区别
    event.stopPropagation()阻止事件冒泡,元素的默认行为仍然会发生
    event.preventDefault()阻止元素的默认行为【a标签的默认跳转、form表单的默认提交】,仍然会发生事件冒泡
    return false 同时阻止事件冒泡和默认事件
    参考:https://blog.csdn.net/Dailoge/article/details/89356970

32、事件的绑定
    1) on
        dom.onclick = function(){}
        dom.onmouseleave = function(){}
    2) addEventListener
        dom.addEventListener('click',function(){})
        dom.addEventListener('mouseleave',function(){})
    3) attachEvent
        兼容性较差(IE低版本下才兼容)

33、常用事件类型
    onload
        window.onload = function(){} 页面加载完毕
    click   点击
    mouseover   光标移入,支持子元素
    mouseout    光标移出,支持子元素

    mouseenter  光标移入,不支持子元素
    mouserleave 光标移出,不支持子元素
    scroll  页面滚动
    keyup   键盘抬起
    keydown 键盘落下
    focus   聚焦
    blur    失焦

34、事件代理(事件委托)
    起因:
        dom节点需要事件处理程序时,直接给它绑定即可。但是如果很多的dom都需要绑定事件处理程序,可以使用for循环,遍历出所有的dom,然后依次给它们绑定事件,但是对于该方法来说,需要不断的与dom节点交互,从而使浏览器的渲染速度变慢,降低效率
    解决:
        通过事件代理将事件绑定在当前元素的父元素上,这样与dom只需要交互一次即可
    原理:
        事件冒泡
            div > table > tr > td > a/span
        当点击当前元素(a/span)时,将逐级向上冒泡到父元素,执行父元素上绑定的事件处理程序。在父元素中可以通过event.target获取当前元素

35、event.target与event.currentTarget
    event.target  事件触发的源头元素
    event.currentTarget 当前触发事件的元素  

36、use strict是什么意思?
    是es5特性,使代码在整个脚本中处于严格模式

    严格模式一些限制:
        1. 变量必须声明后再使用
        2. 函数的参数不能有同名的,否则报错
        3. 不能删除不可删除的属性
        4. 不能使用arguments.callee
        5. 禁止this指向全局
        ...
    好处:
        1. 消除js语法中的一些不合理的、不严谨的地方
        2. 消除代码运行的不安全之处
        3. 提高编译效率

37、BOM【浏览器对象模型】
    1) 超时调用
        var id = setTimeout(function(){},time)
        clearTimeout(id)
    2) 间歇调用
        var id = setInterval(function(){},time)
        clearInterval(id)
    3) Location对象
        assign(url) 加载新的url,在浏览记录中生成一条记录【可以前进、回退】
        replace(url) 用新的url替换旧的url,不会在浏览记录中生成记录【不可以前进、回退】
        reload() 刷新当前页面
    4) 存储对象
        localStorage
            长久的保存数据,保存的数据没有过期时间,除非手动删除
        sessionStorage
            临时保存数据,保存的数据在浏览器或浏览器选项卡关闭时丢失
        localStorage的方法
            localStorage.setItem(key,val) 设置键值
            localStorage.getItem(key) 获取键
            localStorage.removeItem(key) 移除键
            localStorage.clear() 清空键

            存储一个对象时,首先需要将该对象序列化,获取的时候反序列化即可
            localStorage.setItem('userInfo',JSON.stringify(this.obj))             

        localStorage、 sessionStorage、 cookies的区别  

38、get和post的区别
    1) 在浏览器地址栏中输入一个网址访问页面时,一般是get请求
    2) form表单,可以通过method指定提交的方式为get、post
    3) 请求由请求头、请求行、请求数据组成

    区别:
        1) 请求形式
            get把请求的数据放在url上,以?分割url和请求数据
            post把请求的数据放在http的请求体内
        2) 传输数据的大小
            get请求,传输的数据大小有限制
            post请求,传输的数据大小没有限制
        3) 安全性
            post比get请求安全
        4) 发送数据的过程【了解】
            get请求,浏览器会将http header 和data一并发送,服务器响应200
            post请求,会先将http header发送,服务器响应100 conitune,浏览器再发送data,服务器响应200

39、ajax与axios的区别
    ajax    【默认请求格式application/x-www-form-urlencoded】
        ajax({
            url,
            method:'post',
            data:login_form, // 参数默认为键值对形式【查询字符串】key1=val1&key2=val2
            success:()=>{}
        })
        如何利用ajax向后台发送json字符串?
        ajax({
            url,
            method:'post',
            data:JSON.stringify(login_form),
            contentType:'application/json',
            success:()=>{}
        })
    axios   【默认请求格式application/json】
        axios({
            url,
            method:'post',
            data:login_form, // 参数默认为json字符串'{"key1":"val1","key2":"val2"}'
            success:()=>{}
        })
        如何利用axios向后台发送查询字符串?
        axios({
            url,
            method:'post',
            data:qs.stringify(login_form),
            contentType:'application/x-www-form-urlencoded',
            success:()=>{}
        })

40、var、let、const
    声明方式        变量提升        重复声明        块级作用域
      var            允许            允许            不存在
      let           不允许          不允许            存在
     const          不允许          不允许            存在

41、const和Object.freeze()的区别
    const声明一个只读常量,一旦声明,常量的值不允许改变
    Object.freeze()适用于对象,它使对象不可变,也就是不能更改属性值
        let obj = {
            name:'tom'
        }
        Object.freeze(obj);
        obj.name = 'larry';
        obj.age = 13;
        console.log(obj); // {name:'tom'}

42、什么是箭头函数【谈谈你对箭头函数的认识】
    es6中允许使用箭头(=>)定义函数,是对于es5中函数的简化
        function(){}

        ()=>{}
    箭头函数中的this指向该箭头函数外部函数的this

    什么时候不适合使用箭头函数?
        1) 希望函数被提升
        2) 希望函数有名字(箭头函数是一个匿名函数)
        3) 要在函数中使用this/arguments时,由于箭头函数本身是没有this/arguments
        4) 使用函数作为构造函数(箭头函数没有构造函数)
    
43、解构
    1) 数组解构
        等号两边的模式相同时,左边的变量会被赋值等号右边对应位置上的值
            let [age,name] = ['tom',13]
            console.log(name,age); // 13 tom
        数组解构默认值【解构时,允许指定默认值】
            1. 默认值生效的前提:对应位置上是undefined
                let [name='tom'] = [undefined]
                console.log(name); // tom
            2. 默认值可以引用解构赋值的其他变量
                let [name='tom',name2=name] = [];
                console.log(name,name2); // tom tom

    2) 对象解构
        变量必须属性名同名,跟变量的位置无关
            let {age,name} = {name:'tom',age:13}
            console.log(name,age); // tom 13
        对象解构的默认值
            let {name,age,gender='male'} = {name:'tom',age:13}
            console.log(name,age,gender); // tom 13 male

44、对象扩展
    1) 对象属性的简写
        let name = 'tom'
        let obj = {
            name
        }
        ==>
        let obj = {
            name:name
        }

    2) 对象方法的简写
        let obj = {
            name:'tom',
            sayName(){
                console.log('xxx')
            }
        }
        ==>
        let obj = {
            name:'tom',
            sayName:function(){
                console.log('xxx')
            }
        }

    3) 构造函数的扩展 Object.xxx
        Object.is(val1,val2) 判断两个变量是否相等
            该方法和 === 不同
            1、Object.is(NaN,NaN); // true 
            2、Object.is(+0,-0); // false 
        Object.assign()
            1、合并对象
            2、复制对象【克隆】
            let obj = {name:'tom'}
            let res = Object.assign({},obj)
        Object.keys()   键
        Object.values() 值
        Object.entries() 键值对

45、函数的扩展
    1) 函数声明在对象中的简写
        let obj = {
            name:'tom',
            sayName(){
                console.log('xxx')
            }
        }
    2) 函数声明在参数中的简写
        let res = arr.filter((item)=>{
            return item.name === 'tom'
        })
    3) 函数参数的默认值
        使用解构给函数的参数提供默认值
            function sayMsg({name,age,gender='male'}){
                console.log('xxx')
            }
            sayMsg({name:'tom',age:13})

46、数组的扩展
    1) Array.from(v)
        将类数组对象、可遍历对象(Set、Map)转换为数组
    2) Array.of()
        创建数组
        let arr = Array.of(2); // [2]
    3) find和findIndex
        find找出第一个满足条件的元素,如果没有,返回undefined
        findIndex找出第一个满足条件的元素的索引,如果没有,返回-1
    4) keys、values、entries
        遍历数组,都返回遍历器对象,该遍历器对象用于for-of循环

47、Symbol
    含义:
        是一种全新的数据类型,可以用作对象中唯一的属性名
    创建方式:
        let symbol = Symbol();
    用途:
        1、使用Symbol来作为对象的属性名,防止出现覆盖的现象
        2、定义私有的属性、方法

48、Promise对象
    含义:
        就是一个对象,用来传递异步操作的消息。Promise 是一个对象,从它可以获取异步操作的消息。Promise 提供统一的 API,各种异步操作都可以用同样的方法进行处理
    用途:
        用于解决回调地狱
    特点:
        1、对象的状态不受外界影响
        2、一旦状态改变,就不会再变
    方法:    
        Promise.prototype.then()
            请求成功时的回调函数
        Promise.prototype.catch()
            请求失败时的回调函数
        Promise.prototype.finally()
            不管请求成功与否,都会执行该方法
    推荐形式:
        promise.then(()=>{}).catch(()=>{})

49、vue中请求的写法
    async findAllArticle(){
        let article = await get('xxx')
        let id = article[0].id

        let article_detail = await get('xxx',{id})
        console.log(article_detail)
        return article
    }

    this.findAllArticle().then((res)=>{
        console.log(res)
    })

50、什么是mvvm?
    是Model-View-ViewModel缩写,也就是将mvc中controller演变成ViewModel
    Model代表数据模型
    View代表视图
    ViewModel是连接Model与View的桥梁
    mvvm主要解决了mvc中大量的dom操作,使页面的渲染速度变快
    vue中就是采用的mvvm模式
    ...

51、vue的渲染
    1) 声明式渲染
        {{}}
    2) 列表渲染
        v-for
        v-for='(item,index) in arr'
    3) 条件渲染【由条件决定当前元素是否显示】
        v-if
        v-if v-else 
        v-if v-else-if v-else

        v-show【控制display属性,元素始终被渲染】

52、v-if和v-show的区别?
    v-if
        1. 是惰性的(当条件为真时,页面才渲染该元素)
        2. 在切换时,会适当的销毁当前元素内的事件和子组件
        3. 切换时开销大
    v-show
        1. 初次渲染时开销大
        2. 不论条件是否为真,元素始终被渲染,仅控制display属性
    ==>
    频繁切换,使用v-show
    不频繁切换,使用v-if

53、为什么要在v-for的时候加上key?
    含义:
        为每个元素提供唯一标识
    取值:数字

    作用:
        1. 为了高效的更新虚拟DOM
        2. 在使用相同标签名元素的过渡切换时,也会使用到key属性,其目的也是为了让vue可以区分它们,否则vue只会替换其内部属性而不会触发过渡效果
    参考:https://blog.csdn.net/shicl/article/details/81392385?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-2.nonecase&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-2.nonecase

54、vue数据变化但是页面不更新的原因?解决方案?
    原因:
        vue会对data中的数据进行监听,当数据发生改变时,页面会自动更新
        但是在js中,无法监测数组和对象的变化,即vue只是监听了栈区的改变
    现象:
        对象新增属性时,页面无法更新
    方法:
        1) vm.$set【对象新增一个属性】
        2) Object.assign()【对象新增多个属性】
        3) lodash【克隆】clone
        4) vm.$forceUpdate()【强制vue实例重新渲染】

55、属性绑定【动态绑定】
    v-bind: ==> :
    1) style绑定
        <div :style='style'></div>
        data(){
            return {
                style:{
                    color:'red'
                }
            }
        }
    2) class绑定
        <div :class='class'></div>
        data(){
            return {
                class:{
                    item:true
                }
            }
        }
    3) key绑定
        <div v-for='item in arr' :key='item.id'></div>

56、vue事件绑定
    v-on: ==> @
    1) 事件绑定
        v-on:click='js表达式'
        @click='函数'

    2) 事件传参
        @click='handler("参数")'

        <div v-for='(item,index) in arr' :key='item.id' @click='handler(item,index)'></div>
        methods:{
            handler(item,index){
                console.log(item,index)
            }
        }
    
    3) 事件修饰符
        @click.xxx
            @click.prevent
                阻止事件默认行为
            @click.stop
                阻止单击事件继续传播

    4) 按键修饰符
        @keyup.enter='' 【回车键】
    
57、vue生命周期
    beforeCreate
        无法访问vue实例data中的数据和methods中的方法
    created
        可以访问vue实例data中的数据和methods中的方法
        页面加载时查询数据
    beforeMount
        完成模板编译
    mounted
        完成数据绑定,页面首次出现数据
    beforeUpdate
        data中的数据更新前
    updated
        data中的数据被更改
    beforeDestory
        页面销毁前
    destoryed
        页面销毁

58、计算属性(computed)
    将data中的数据进行处理之后返回成新的变量
    1、计算属性的用法跟data中的数据类似
    2、原有数据改变时,计算属性会立即重新执行
    3、对于复杂逻辑,推荐使用计算属性
    4、多次渲染时,计算属性只执行一次,而方法会执行多次

59、过滤器(filter)
    用于文本格式化
    1) 使用范围
        双大括号
            {{date | dateFormat}}
        v-bind
    2) 全局过滤器和局部顾虑器
        1. 全局注册【所有的vue实例都可以调用】
            Vue.filter('dateFormat',function(dateStr){
                return moment(dateStr).format('YYYY-MM-DD')
            })
        2. 局部注册
            methods:{},
            filters:{
                dateFormat(dateStr){
                    return moment(dateStr).format('YYYY-MM-DD')
                }
            }
        3. 注意:
            就近原则

60、监听(watch)
    监听data中数据的变化
    1) 一般监听
        methods:{},
        watch:{
            msg:function(now,old){
                console.log('xxx')
            }
        }
    2) 深度监听【一般监听引用数据类型中值的变化】
        watch:{
            params:{
                handler:function(now,old){
                    console.log('xxx')
                },
                deep:true
            }
        }

61、组件
    1) 组件注册及使用
        1. 全局注册
            Vue.component('briup-div',{
                template:`<div>hello vue</div>`
            })
        2. 局部注册
            components:{
                'briup-div':{
                  template:`<div>hello vue</div>`,
                  data(){
                      return {}
                  }
                }
            }
        3. 使用【可复用】
            <briup-div></briup-div>
            <briup-div></briup-div>

    2) 组件传参【props】
        Vue.component('briup-div',{
            template:`<div>{{msg}}</div>`,
            props:['msg']
        })
        <briup-div msg='hello vue'></briup-div>

        1. props用法和data中的数据类似,可以直接使用{{}}渲染
        2. 参数的数量是任意的
    
    3) 组件参数的限制
        1. 类型声明
            props:{
                参数:参数类型
            }
            props:{
                a:String,
                b:Boolean,
                c:Array,
                d:Object
                ...
            }
        2. 参数验证
            props:{
                title:{
                    type:String,
                    required:true
                }
            }

    4) 单向数据流【参数的传递】【父组件 --> 子组件】
    
    5) 自定义事件【子组件 --> 父组件】
        子组件通过this.$emit('xxx'),通知父组件进行变量的改变
        父组件通过@xxx监听

    6) 插槽
        子组件通过slot接收父组件传递过来的子模板【标签】
        1. 默认插槽
        2. 具名插槽
        3. 作用域插槽(回调插槽)
    
    7) 动态组件
        <keep-alive>
            <component :is='组件名'></component>
        </keep-alive>

62、渲染函数【为开发者提供dom的底层操作接口】
    1) 语法
        render :function(createElement){
            return createElement('div',this.msg)
        }
        ==> 
        <div>{{msg}}</div>
    2) 参数
        标签名 + 数据对象 + 标签内容

63、路由
    1) 路由定义
        1. 定义组件
        2. 创建router实例
        3. 定义路由
            let router = new VueRouter({
                routes:[{
                    path:'/category',
                    component:Category
                },{},{}]
            })
        4. 将router注入到vue的根组件
        5. 路由出口,渲染路由对应的组件
        6. 路由切换

    2) 匹配所有路由【404页面】
        let Wrong = {
            template:`<div>404</div>'
        }
        let router = new VueRouter({
            routes:[{
                path:'/category',
                component:Category
            },{

            },{
                path:'*',
                component:Wrong
            }]
        })
    
    3) 编程式导航
        this.$router.push()
            跳转到指定路由,会在history栈添加一条记录【可以前进后退】
        this.$router.replace()
            跳转到指定路由,不会在history栈添加一条记录【不可以前进后退】
        this.$router.go(n)
            在history记录中前进后退n步
            this.$router.go(0)  刷新当前页
            this.$router.go(-1)  回到上一页

    4) 命名路由
        let router = new VueRouter({
            routes:[{
                name:'category',
                path:'/category',
                component:Category
            },{},{}]
        })
        路由携带参数的两种方式
            1. push【将参数暴露在url上】
                参数传递:this.$router.push({path:'/',query:{categoryId}})
                参数接收:this.$route.query.categoryId
            2. 命名路由【不会将参数暴露在url上】
                参数传递:this.$router.push({name:'category',params:{categoryId}})
                参数接收:this.$route.params.categoryId

    5) 重定向
        let router = new VueRouter({
            routes:[{
                path:'/',
                redirect:'/category'
            }]
        })
        当访问/时,重定向到/category
    
    6) 路由模式
        1. hash模式 有#【默认】
        2. history模式 没有#
        let router = new VueRouter({
            mode:history'',
            routes:[{
                path:'/',
                redirect:'/category'
            }]
        })

64、状态机(vuex)
    作用:
        1) 可以将数据进行统一的维护,以便其他组件共享
        2) 可以将请求代码进行封装,供其他组件调用
    使用步骤:
        1) 创建vuex对象
            let store = new Vuex.Store({
                namespaced:true,
                state:{},
                getters:{},
                mutations:{},
                actions:{}
            })
        2) 注入根组件
            new Vue({
                store
            })
        3) 使用
            vue实例对象中通过this访问store【this.$store】
            1. state访问
                this.$store.state.xxx

                computed:{
                    ...mapState('命名空间',['xxx'])
                }
            2. getters访问
                this.$store.getters.xxx

                computed:{
                    ...mapGetters('命名空间',['xxx'])
                }
            3. mutations访问
                this.$store.commit('xxx')

                methods:{
                    ...mapMutations('',['xxx'])
                }
            4. actions访问
                this.$store.dispatch('xxx')

                methods:{
                    ...mapActions('',['xxx'])

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值