九阳真经前端篇——更新至ES6

HTML

HTML语义化

HTML语义化就是让页面内容结构化,它有如下优点:

  • 易于用户阅读,样式丢失的时候能让页面呈现清晰的结构
  • 有利于SEO,搜索引擎根据标签来确定上下文和各个关键字的权重
  • 方便其他设备解析,如盲人阅读器根据语义化渲染网页
  • 有利于开发和 维护,语义化更具有可读性,代码更好维护,与CSS关系更和谐

如:

<header>代表头部
<nav>代表超链接区域
<main>定义文档主要内容
<article>可以表示文章、博客等内容
<aside>通常表示侧边栏或嵌入内容
<footer>代表尾部

HTML5新标签(待补充)

<header>,<footer><aside><nav><video><audio><canvas>

CSS

盒子模型

盒模型分为标准和模型和怪异盒模型(IE盒模型)

box-sizing:content-box	//标准盒模型
box-sizing:border-box	//怪异盒模型

九阳真经前端篇——更新至ES6_第1张图片

标准盒模型:元素的宽度等于style里的width+margin+border+padding宽度

九阳真经前端篇——更新至ES6_第2张图片

如下代码,整个宽高还是120px

div{
    box-sizing: content-box;
    margin: 10px;
    width: 100px;
    height: 100px;
    padding: 10px;
}

怪异盒模型:元素宽度等于style里的width宽度

九阳真经前端篇——更新至ES6_第3张图片

如下代码,整个宽高还是100px

div{
    box-sizing: border-box;
    margin: 10px;
    width: 100px;
    height: 100px;
    padding: 10px;
}

rem与em的区别

rem是根据根的font-size变化,而em是根据父级的font-size变化

CSS选择器

  • css常用选择器
通配符:*
ID选择器:#ID
类选择器:.class
元素选择器:p、a    等
后代选择器:p span、div a   等
伪类选择器:a:hover 等
属性选择器:input[type="text"]
  • css选择器权重

!important -> 行内样式 -> #id -> .class -> 元素和伪元素 -> * -> 继承 -> 默认

CSS3新特性(待补充)

transition:过渡
transform:旋转,缩放,移动或者倾斜
animation:动画
gradient:渐变
shadow:阴影
border-radius:圆角

行内元素和块级元素

  • 行内元素(display;inline)

宽度和高度是由内容决定,与其他元素共占一行的元素,我们将其叫行内元素,例如:

  • 块级元素

默认宽度由父容器决定,默认高度由内容决定,独占一行并且可以设置宽高的元素,我们将其叫做块级元素,例如:

相对定位和绝对定位的区别

  • position:absolute

绝对定位:是相对于元素最近的已定位的祖先元素

  • position:relative

相对定位:相对定位是相对于元素在文档中的初始位置

Flex布局(待补充)

复习链接:https://juejin.im/post/5d428c5451882556dc30535c

BFC

复习链接:https://blog.csdn.net/wyf521995/article/details/103106913

简单描述

  • 什么是BFC?

BFC格式化上下文,它是一个独立的渲染区域,让处于 BFC 内部的元素和外部的元素相互隔离,使内外元素的定位不会相互影响

  • 如何产生BFC?
display: inline-block

position: absolute/fixed
  • BFC作用

BFC最大的一个作用就是:在页面上有一个独立隔离容器,容器内的元素和容器外的元素布局不会相互影响

解决上外边距重叠;重叠的两个box都开启bfc;
解决浮动引起高度塌陷;容器盒子开启bfc
解决文字环绕图片;左边图片div,右边文字容器p,将p容器开启bfc

水平垂直居中(待补充)

  • Flex布局
display: flex  //设置Flex模式
flex-direction: column  //决定元素是横排还是竖着排
flex-wrap: wrap     //决定元素换行格式
justify-content: space-between  //同一排下对齐方式,空格如何隔开各个元素
align-items: center     //同一排下元素如何对齐
align-content: space-between    //多行对齐方式
  • 水平居中
行内元素:display: inline-block;
块级元素:margin: 0 auto;
Flex: display: flex; justify-content: center
  • 垂直居中
行高 = 元素高:line-height: height
flex: display: flex; align-item: center

less,sass,styus三者的区别

  • 变量

Sass声明变量必须是『$』开头,后面紧跟变量名和变量值,而且变量名和变量值需要使用冒号:分隔开。

Less 声明变量用『@』开头,其余等同 Sass。

Stylus 中声明变量没有任何限定,结尾的分号可有可无,但变量名和变量值之间必须要有『等号』。

  • 作用域

Sass:三者最差,不存在全局变量的概念

Less:最近的一次更新的变量有效,并且会作用于全部的引用!

Stylus:Sass 的处理方式和 Stylus 相同,变量值输出时根据之前最近的一次定义计算,每次引用最近的定义有效;

  • 嵌套

三种 css 预编译器的「选择器嵌套」在使用上来说没有任何区别,甚至连引用父级选择器的标记 & 也相同

  • 继承

Sass和Stylus的继承非常像,能把一个选择器的所有样式继承到另一个选择器上。使用『@extend』开始,后面接被继承的选择器。Stylus 的继承方式来自 Sass,两者如出一辙。 Less 则又「独树一帜」地用伪类来描述继承关系;

  • 导入@import

    • Sass 中只能在使用 url() 表达式引入时进行变量插值

      $device: mobile;
      @import url(styles.#{$device}.css);
      
    • Less 中可以在字符串中进行插值

      @device: mobile;
      @import "styles.@{device}.css";
      
      
    • Stylus 中在这里插值不管用,但是可以利用其字符串拼接的功能实现

      device = "mobile"
      @import "styles." + device + ".css"
      

link与@import区别于选择(待补充)

<style type="text/css">
	@import url(CSS文件路径地址);
</style>
<link href="CSSurl路径" rel="stylesheet" type="text/css" /

link功能较多,可以定义 RSS,定义 Rel 等作用,而@import只能用于加载 css;

当解析到link时,页面会同步加载所引的 css,而@import所引用的 css 会等到页面加载完才被加载;

@import需要 IE5 以上才能使用;

link可以使用 js 动态引入,@import不行

多行文本的文本省略号(待补充)

overflow : hidden;
text-overflow: ellipsis;
display: -webkit-box;
-webkit-line-clamp: 3;
-webkit-box-orient: vertical

JavaScript

JS的几条基本规范

1、不要在同一行声明多个变量
2、请使用===/==来比较true/false或者数值
3、使用对象字面量替代new Array这种形式
4、不要使用全局变量
5、Switch语句必须带有default分支
6、函数不应该有时候有返回值,有时候没有返回值
7、For循环必须使用大括号
8IF语句必须使用大括号
9for-in循环中的变量 应该使用var关键字明确限定作用域,从而避免作用域污染

JS引用方法

  • 行内引入

    <body>
      <input type="button" onclick="alert('行内引入')" value="按钮"/>
      <button onclick="alert(123)">点击我</button>
    </body>
    
  • 内部引入

<script>
  window.onload = function() {
    alert("js 内部引入!");
  }
</script>
  • 外部引入

    <body>
      <div></div>
    
      <script type="text/javascript" src="./js/index.js"></script>
    </body>
    

注意:

1,不推荐写行内或者HTML中插入

JS的基本数据类型(待补充)

Undefined、Null、Boolean、Number、String、新增:Symbol

数组操作(待补充)

在 JavaScript 中,用得较多的之一无疑是数组操作,这里过一遍数组的一些用法

map: 遍历数组,返回回调返回值组成的新数组
forEach: 无法break,可以用try/catchthrow new Error来停止
filter: 过滤
some: 有一项返回true,则整体为true
every: 有一项返回false,则整体为false
join: 通过指定连接符生成字符串
push / pop: 末尾推入和弹出,改变原数组, 返回推入/弹出项【有误】
unshift / shift: 头部推入和弹出,改变原数组,返回操作项【有误】
sort(fn) / reverse: 排序与反转,改变原数组
concat: 连接数组,不影响原数组, 浅拷贝
slice(start, end): 返回截断后的新数组,不改变原数组
splice(start, number, value...): 返回删除元素组成的数组,value 为插入项,改变原数组
indexOf / lastIndexOf(value, fromIndex): 查找数组项,返回对应的下标
reduce / reduceRight(fn(prev, cur), defaultPrev): 两两执行,prev 为上次化简函数的return值,cur 为当前值(从第二项开始)

JS有哪些内置对象

Object是JavaScript中所有对象的父对象

数据封装对象:Object、Array、Boolean、Number和String
其他对象:Function、Arguments、Math、Date、RegExp、Error

get请求传参长度的误区

误区:我们经常说get请求参数的大小存在限制,而post请求的参数大小是无限制的

实际上HTTP 协议从未规定 GET/POST 的请求长度限制是多少。对get请求参数的限制是来源与浏览器或web服务器,浏览器或web服务器限制了url的长度。为了明确这个概念,我们必须再次强调下面几点:

​ 1、HTTP 协议 未规定 GET 和POST的长度限制

​ 2、GET的最大长度显示是因为 浏览器和 web服务器限制了 URI的长度

​ 3、不同的浏览器和WEB服务器,限制的最大长度不一样

​ 4、要支持IE,则最大长度为2083byte,若只支持Chrome,则最大长度 8182byte

补充get和post请求在缓存方面的区别

  • get请求类似于查找的过程,用户获取数据,可以不用每次都与数据库连接,所以可以使用缓存。
  • post不同,post做的一般是修改和删除的工作,所以必须与数据库交互,所以不能使用缓存。因此get请求适合于请求缓存。

闭包

  • 什么是闭包

    函数A里面办函了函数B,而函数B里面使用了函数A的变量,那么函数B被称为闭包

    又或者:闭包就是能够读取其他函数内部变量的函数

    function A() {
      var a = 1;
      function B() {
        console.log(a);
      }
      return B();
    }
    
  • 闭包的特征

    • 函数内再嵌套函数
    • 内部函数可以引用外层的参数和变量
    • 参数和变量不会被垃圾回收机制回收
  • 对闭包的理解

    使用闭包主要是为了设计私有的方法和变量.闭包的优点是可以避免全局变量的污染,缺点是闭包会常驻内存,会增大内存使用量,使用不当很容易曹成内存泄漏,在js中,函数即闭包,只有函数才会产生作用域的概念

    闭包最大的用处有两个,一个是可以读取函数内部的变量,另一个就是让这些变量时钟保持在内存中

    闭包的另一个用处就是封装对象的私有属性和私有方法

  • 闭包的好处

    能够实现封装和缓存等

  • 闭包的坏处

    就是消耗内存,不正当使用会造成内存溢出的问题

  • 使用闭包的注意点

    由于闭包会使得函数中的变量都被保存在内存中,内存消耗恒大,所以不能滥用闭包,否则会造成网页的性能问题,在IE中可能会导致内存泄漏

    解决方法是:在退出函数之前,将不使用的局部变量全部删除

  • 闭包的经典问题

    for(var i = 0; i < 3; i++) {
      setTimeout(function() {
        console.log(i);
      }, 1000);
    }
    
    
    

    这段代码输出:

    答案:33
    解析:首先,for 循环是同步代码,先执行三遍 for,i 变成了 3;然后,再执行异步代码 setTimeout,这时候输出的 i,只能是 33

    有什么办法依次输出0 1 2

    • 第一种方法:使用let

      for(let i = 0; i < 3; i++) {
        setTimeout(function() {
          console.log(i);
        }, 1000);
      }
      

      在这里,每个 let 和代码块结合起来形成块级作用域,当 setTimeout() 打印时,会寻找最近的块级作用域中的 i,所以依次打印出 0 1 2

      如果这样不明白,我们可以执行下边这段代码

      for(let i = 0; i < 3; i++) {
        console.log("定时器外部:" + i);
        setTimeout(function() {
          console.log(i);
        }, 1000);
      }
      

      此时浏览器依次输出的是:

      定时器外部:0
      定时器外部:1
      定时器外部:2
      0
      1
      2
      

      即代码还是先执行 for 循环,但是当 for 结束执行到了 setTimeout 的时候,它会做个标记,这样到了 console.log(i) 中,i 就能找到这个块中最近的变量定义

    • 第二种方法

      使用立即执行函数解决闭包问题

      for(let i = 0; i < 3; i++) {
        (function(i){
          setTimeout(function() {
            console.log(i);
          }, 1000);
        })(i)
      }
      
      

JS作用域及作用域链

一般情况下,变量取值到创建这个变量的函数的作用域中取值。

但是如果在当前作用域中没有查到值,就会向上级作用域去查,直到查到全局作用域,这么一个查找过程形成的链条就叫做作用域链

九阳真经前端篇——更新至ES6_第5张图片

原型和原型链

  • 原型和原型链的概念

    每个对象都会在其内部初始化一个属性,就是prototype(原型),当我们访问一个对象的属性时,如果这个对象内部不存在这个属性,那么他就会去prototype里找这个属性,这个prototype又会有自己的prototype,于是就这样一直找下去

  • 原型和原型链的关系

    instance.constructor.prototype = instance.__proto__
    
  • 原型和原型链的特点

    JavaScript对象是通过引用来传递的,我们创建的每个新对象实体中并没有一份属于自己的原型副本。当我们修改原型时,与之相关的对象也会继承这一改变,当我们需要一个属性的时,Javascript引擎会先看当前对象中是否有这个属性, 如果没有的就会查找他的Prototype对象是否有这个属性,如此递推下去,一直检索到 Object 内建对象

组件化和模块化

组件化

  • 为什么要组件化开发

    有时候页面代码量太大,逻辑太多或者同一个功能组件在许多页面均有使用,维护起来相当复杂,这个时候,就需要组件化开发来进行功能拆分、组件封装,已达到组件通用性,增强代码可读性,维护成本也能大大降低

  • 组件化开发的优点

    很大程度上降低系统各个功能的耦合性,并且提高了功能内部的聚合性。这对前端工程化及降低代码的维护来说,是有很大的好处的,耦合性的降低,提高了系统的伸展性,降低了开发的复杂度,提升开发效率,降低开发成本

  • 组件化开发的原则

    • 专一
    • 可配置性
    • 标准型
    • 复用性
    • 可维护性

模块化

  • 为什么要模块化

    早期的javascript版本没有块级作用域、没有类、没有包、也没有模块,这样会带来一些问题,如复用、依赖、冲突、代码组织混乱等,随着前端的膨胀,模块化显得非常迫切

  • 模块化的好处

    • 避免变量污染,命名冲突
    • 提高代码复用率
    • 提高了可维护性
    • 方便依赖关系管理
  • 模块化的几种方法

    • 函数封装

      var myModule = {
          var1: 1,
          
          var2: 2,
          
          fn1: function(){
          
          },
          
          fn2: function(){
          
          }
      }
      

      总结:这样避免了变量污染,只要保证模块名唯一即可,同时同一模块内的成员也有了关系
      缺陷:外部可以睡意修改内部成员,这样就会产生意外的安全问题

    • 立即执行函数表达式

      var myModule = (function(){
          var var1 = 1;
          var var2 = 2;
          
          function fn1(){
          
          } 
          
          function fn2(){
          
          }
      
      return {
          fn1: fn1,
          fn2: fn2
      };
      })();
      
      

      总结:这样在模块外部无法修改我们没有暴露出来的变量、函数

      缺点:功能相对较弱,封装过程增加了工作量,仍会导致命名空间污染可能、闭包是有成本的

图片的预加载和懒加载

  • 预加载:提前加载图片,当用户需要查看时可以直接从本地缓存中渲染
  • 懒加载:懒加载的主要目的是作为服务器前端的优化,减少请求数或延迟请求数

两种技术的本质:两者的行为是相反的,一个是提前加载,一个是迟缓甚至不加载。预加载则会增加服务器前端压力,懒加载对服务器有一定的缓解压力作用。

mouseover和 mouseenter的区别

  • mouseover:当鼠标移入元素或者其他子元素都会触发事件,所以有一个重复触发,冒泡的过程,对应的移除事件是mouseout
  • mouseenter:当鼠标移除元素本身(不包含元素的子元素)会触发事件,也就是不会冒泡,对应的移除事件是mouseleave

解决异步回调地狱(待补充)

promise,generator,async/await

对This对象的理解(待补充)

  • this总是指向函数的直接调用者(而非间接调用者)
  • 如果有new关键字,this指向new出来的那个对象
  • 在事件中,this指向触发这个事件的对象,特殊的是,IE中的attachEvent中的this总是指向全局对象Window

Vue

Vue生命周期

  • 什么是Vue生命周期?

参考博文:https://blog.csdn.net/wyf521995/article/details/103114989

简单描述:Vue 实例从创建到销毁的过程,就是生命周期。也就是从开始创建、初始化数据、编译模板、挂载Dom→渲染、更新→渲染、卸载等一系列过程,我们称这是 Vue 的生命周期

  • Vue生命周期的作用是什么?

    它的生命周期中有多个事件钩子,让我们在控制整个Vue实例的过程时更容易形成好的逻辑

  • Vue生命周期总共有几个阶段?

    它可以总共分为8个阶段:创建前/后, 载入前/后,更新前/后,销毁前/销毁后

  • 第一次页面加载会触发哪几个钩子?

    第一次页面加载时会触发 beforeCreate, created, beforeMount, mounted 这几个钩子

  • DOM渲染在哪个周期中就已经完成?

    DOM 渲染在 mounted 中就已经完成了

  • 每个生命周期适合哪些场景?

    生命周期钩子的一些使用方法:

    beforecreate : 可以在这加个loading事件,在加载实例时触发

    created : 初始化完成时的事件写在这里,如在这结束loading事件,异步请求也适宜在这里调用

    mounted : 挂载元素,获取到DOM节点

    updated : 如果对数据统一处理,在这里写上相应函数

    beforeDestroy : 可以做一个确认停止事件的确认框

    nextTick : 更新数据后立即操作dom

v-show与v-if的区别

v-show是css切换,v-if是完整的销毁和重新创建

使用 频繁切换时用v-show,运行时较少改变时用v-if

v-if=‘false’ v-if是条件渲染,当false的时候不会渲染

开发中常用的指令有哪些?

v-model :一般用在表达输入,很轻松的实现表单控件和数据的双向绑定
v-html: 更新元素的 innerHTML
v-show 与 v-if: 条件渲染, 注意二者区别
v-on : click: 可以简写为@click,@绑定一个事件。如果事件触发了,就可以指定事件的处理函数 v-for:基于源数据多次渲染元素或模板块 v-bind: 当表达式的值改变时,将其产生的连带影响,响应式地作用于 DOM

绑定Class的数组方法

  • 对象方法

    v-bind:class="{'orange': isRipe, 'green': isNotRipe}"
    
  • 数组方法

    v-bind:class="[class1, class2]"
    
  • 行内

    v-bind:style="{color: color, fontSize: fontSize+'px' }"
    

组件之间的传值通信

  • 父组件给子组件传值

    使用props,字组件可以使用props接收父组件传递的数据

    父组件vue模板father.vue

    <template>
        <child :msg="message"></child>
    </template>
    
    <script>
    import child from './child.vue';
    export default {
        components: {
            child
        },
        data () {
            return {
                message: 'father message';
            }
        }
    }
    </script>
    
    

    子组件vue模板child.vue

    <template>
        <div>{{msg}}</div>
    </template>
    
    <script>
    export default {
        props: {
            msg: {
                type: String,
                required: true
            }
            //我觉得这样写有点麻烦,直接用数组接收就可以了
            /*
        props:['msg'],
            
            */
        }
    }
    </script>
    
    
  • 子组件向父组件通信

    父组件向子组件传递事件方法,子组件通过$emit触发事件,回调给父组件

    子组件vue模板child.vue

    <template>
        <button @click="handleClick">点我</button>
    </template>
    
    <script>
    export default {
        props: {
            msg: {
                type: String,
                required: true
            }
        },
        methods () {
            handleClick () {
                //........
                this.$emit('msgFunc',msg);
            }
        }
    }
    </script>
    
    

    父组件vue模板fatehe.vue

    <template>
        <child @msgFunc="func"></child>
    </template>
    
    <script>
    import child from './child.vue';
    export default {
        components: {
            child
        },
        methods: {
            func (msg) {
                console.log(msg);
            }
        }
    }
    </script>
    
    
  • 非父子,兄弟组件之间通信

    可以通过实例一个vue实例Bus作为媒介,要相互通信的兄弟组件之中,都引入Bus,然后通过分别调用Bus事件触发和监听来实现通信和参数传递

    bus.js代码如下:

    import Vue from 'vue'
    export default new Vue()
    
    

    在需要通信的组件都引入Bus.js:

    <template>
    	<button @click="toBus">子组件传给兄弟组件</button>
    </template>
    
    <script>
    import Bus from '../common/js/bus.js'
    export default{
    	methods: {
    	    toBus () {
    	        Bus.$emit('on', '来自兄弟组件')
    	    }
    	  }
    }
    </script>
    
    

    另一个组件也import Bus.js 在钩子函数中监听on事件

    import Bus from '../common/js/bus.js'
    export default {
        data() {
          return {
            message: ''
          }
        },
        mounted() {
           Bus.$on('on', (msg) => {
             this.message = msg
           })
         }
       }
    
    

    详细可以参考文章:https://blog.emier.cn/post/2019-11-17-vue-jing-dian-mian-shi-ti-yu-zhi-shi-dian-chuan-shao/

路由跳转方式

1<router-link to='home'> router-link标签会渲染为<a>标签,咋填template中的跳转都是这种;

2,另一种是编程是导航 也就是通过js跳转 比如 router.push('/home')

详细可参考文章:https://blog.emier.cn/post/2019-11-17-vue-jing-dian-mian-shi-ti-yu-zhi-shi-dian-chuan-shao/

MVVM

M - Model,Model 代表数据模型,也可以在 Model 中定义数据修改和操作的业务逻辑

V - View,View 代表 UI 组件,它负责将数据模型转化为 UI 展现出来

VM - ViewModel,ViewModel 监听模型数据的改变和控制视图行为、处理用户交互,简单理解就是一个同步 View 和 Model 的对象,连接 Model 和 View

computed和watch有什么区别?

computed:

  1. computed是计算属性,也就是计算值,它更多用于计算值的场景
  2. computed具有缓存性,computed的值在getter执行后是会缓存的,只有在它依赖的属性值改变之后,下一次获取computed的值时才会重新调用对应的getter来计算
  3. computed适用于计算比较消耗性能的计算场景

watch:

  1. 更多的是「观察」的作用,类似于某些数据的监听回调,用于观察props $emit或者本组件的值,当数据变化时来执行回调进行后续操作
  2. 无缓存性,页面重新渲染时值不变化也会执行

小结

  1. 当我们要进行数值计算,而且依赖于其他数据,那么把这个数据设计为computed
  2. 如果你需要在某个数据变化时做一些事情,使用watch来观察这个数据变化

key

参考文章:https://www.jianshu.com/p/4bdd2690859c

组件中的data为什么是函数?

为什么组件中的data必须是一个函数,然后return一个对象,而new Vue实例里,data可以直接是一个对象?

// data
data() {
  return {
	message: "子组件",
	childName:this.name
  }
}

// new Vue
new Vue({
  el: '#app',
  router,
  template: '',
  components: {App}
})

因为组件是用来复用的,JS里对象是引用关系,这样作用域没有隔离,而new Vue的实例,是不会被复用的,因此不存在引用对象问题

Class与Style如何动态绑定?

Class 可以通过对象语法和数组语法进行动态绑定

  • class对象语法

    <div v-bind:class="{ active: isActive, 'text-danger': hasError }"></div>
    
    data: {
      isActive: true,
      hasError: false
    }
    
  • class数组语法

    <div v-bind:class="[isActive ? activeClass : '', errorClass]"></div>
    
    data: {
      activeClass: 'active',
      errorClass: 'text-danger'
    }
    
  • style对象语法

    <div v-bind:style="{ color: activeColor, fontSize: fontSize + 'px' }"></div>
    
    data: {
      activeColor: 'red',
      fontSize: 30
    }
    
    
  • style数组语法

    <div v-bind:style="[styleColor, styleSize]"></div>
    
    data: {
      styleColor: {
         color: 'red'
       },
      styleSize:{
         fontSize:'23px'
      }
    }
    

vue的单项数据流(待补充)

keep-alive(待补充)

v-model的原理

vue 项目中主要使用 v-model 指令在表单 input、textarea、select 等元素上创建双向数据绑定,我们知道 v-model 本质上不过是语法糖,v-model 在内部为不同的输入元素使用不同的属性并抛出不同的事件:

  • text 和 textarea 元素使用 value 属性和 input 事件;
  • checkbox 和 radio 使用 checked 属性和 change 事件;
  • select 字段将 value 作为 prop 并将 change 作为事件;

以input表单元素为例:

<input v-model='something'>

相当于:

<input v-bind:value="something" v-on:input="something = $event.target.value">

如果在自定义组件中,v-model 默认会利用名为 value 的 prop 和名为 input 的事件,如下所示:

父组件:
<ModelChild v-model="message"></ModelChild>

子组件:
<div>{{value}}</div>

props:{
    value: String
},
methods: {
  test1(){
     this.$emit('input', '小红')
  },
},

nextTick() -待补充

在下次DOM更新循环结束之后执行延迟回调。在修改数据之后,立即使用的这个回调函数,获取更新后的DOM

// 修改数据
vm.msg = 'Hello'
// DOM 还未更新
Vue.nextTick(function () {
  // DOM 更新
})

Vue插槽(待补充)

  • 匿名插槽

    当子组件模板只有一个没有属性的插槽时,
    父组件传入的整个内容片段将插入到插槽所在的 DOM 位置,
    并替换掉插槽标签本身

  • 命名插槽

    solt元素可以用一个特殊的特性name来进一步配置如何分发内容。
    多个插槽可以有不同的名字。 这样可以将父组件模板中 slot 位置,
    和子组件 slot 元素产生关联,便于插槽内容对应传递

  • 作用域插槽

    在父级中,具有特殊特性 slot-scope 的 元素必须存在,
    表示它是作用域插槽的模板。slot-scope 的值将被用作一个临时变量名,
    此变量接收从子组件传递过来的 prop 对象

Vue-Router有哪几种导航钩子?

全局前置守卫:
    const router = new VueRouter({ ... })

    router.beforeEach((to, from, next) => {
      // ...
    })
全局解析守卫:
你可以用 router.beforeResolve 注册一个全局守卫。这和 router.beforeEach 类似,
区别是在导航被确认之前,同时在所有组件内守卫和异步路由组件被解析之后,解析守卫就被调用。

全局后置钩子:
你也可以注册全局后置钩子,然而和守卫不同的是,这些钩子不会接受 next 函数也不会改变导航本身:

router.afterEach((to, from) => {
  // ...
})

路由独享的守卫:

const router = new VueRouter({
  routes: [
    {
      path: '/foo',
      component: Foo,
      beforeEnter: (to, from, next) => {
        // ...
      }
    }
  ]
})
组件内的守卫:
你可以在路由组件内直接定义以下路由导航守卫:
const Foo = {
  template: `...`,
  beforeRouteEnter (to, from, next) {
    // 在渲染该组件的对应路由被 confirm 前调用
    // 不!能!获取组件实例 `this`
    // 因为当守卫执行前,组件实例还没被创建
  },
  beforeRouteUpdate (to, from, next) {
    // 在当前路由改变,但是该组件被复用时调用
    // 举例来说,对于一个带有动态参数的路径 /foo/:id,在 /foo/1 和 /foo/2 之间跳转的时候,
    // 由于会渲染同样的 Foo 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。
    // 可以访问组件实例 `this`
  },
  beforeRouteLeave (to, from, next) {
    // 导航离开该组件的对应路由时调用
    // 可以访问组件实例 `this`
  }
}

vuex(待学待补充)

  • vuex是什么?

    vuex 就是一个仓库,仓库里放了很多对象。其中 state 就是数据源存放地,对应于一般 vue 对象里面的 data

    state 里面存放的数据是响应式的,vue 组件从 store 读取数据,若是 store 中的数据发生改变,依赖这相数据的组件也会发生更新

    它通过 mapState 把全局的 state 和 getters 映射到当前组件的 computed 计算属性

  • 五种属性

    • state
    • mutations
    • getters
    • action
  • 总结

    vuex 一般用于中大型 web 单页应用中对应用的状态进行管理,对于一些组件间关系较为简单的小型应用,使用 vuex 的必要性不是很大,因为完全可以用组件 prop 属性或者事件来完成父子组件之间的通信,vuex 更多地用于解决跨组件通信以及作为数据中心集中式存储数据

你对Vue项目进行哪些优化?

  • 代码层面的优化

    v-if 和 v-show 区分使用场景
    computed 和 watch  区分使用场景
    v-for 遍历必须为 item 添加 key,且避免同时使用 v-if
    长列表性能优化
    事件的销毁
    图片资源懒加载
    路由懒加载
    第三方插件的按需引入
    优化无限列表性能
    服务端渲染 SSR or 预渲染
    
  • webpack层面的优化

    Webpack 对图片进行压缩
    减少 ES6 转为 ES5 的冗余代码
    提取公共代码
    模板预编译
    提取组件的 CSS
    优化 SourceMap
    构建结果输出分析
    Vue 项目的编译优化
    
    
  • 基础的web技术优化

    开启 gzip 压缩
    浏览器缓存
    CDN 的使用
    使用 Chrome Performance 查找性能瓶颈

补充

Vue路由的两种模式

小白回答:hash模式url带#号,history模式不带#号

大牛解答:hash模式url里面永远带着#号,我们在开发当中默认使用这个模式。那么什么时候要用history模式呢?如果用户考虑url的规范那么就需要使用history模式,因为history模式没有#号,是个正常的url适合推广宣传。当然其功能也有区别,比如我们在开发app的时候有分享页面,那么这个分享出去的页面就是用vue或是react做的,咱们把这个页面分享到第三方的app里,有的app里面url是不允许带有#号的,所以要将#号去除那么就要使用history模式,但是使用history模式还有一个问题就是,在访问二级页面的时候,做刷新操作,会出现404错误,那么就需要和后端人配合让他配置一下apache或是nginx的url重定向,重定向到你的首页路由上就ok啦。

hash与history的区别:

hash history
url显示 有#,很Low 无#,好看
回车刷新 可以加载到hash值对应页面 一般就是404掉了
支持版本 支持低版本浏览器和IE浏览器 HTML5新推出的API

hash模式
我们先来认识下这位朋友#,这个#就是hash符号,中文名哈希符或锚点,当然这在我们前端领域姑且这么称呼。

然后哈希符后面的值,我们称之为哈希值。OK,接下来我们继续分析他的原理。路由的哈希模式其实是利用了window可以监听onhashchange事件,也就是说你的url中的哈希值(#后面的值)如果有变化,前端是可以做到监听并做一些响应(搞点事情),这么一来,即使前端并没有发起http请求他也能够找到对应页面的代码块进行按需加载。

后来人们给他起了一个霸气的名字叫前端路由,成为了单页应用标配。

history模式
我们先介绍一下H5新推出的两个神器:pushState与replaceState

具体自行百度,简而言之,这两个神器的作用就是可以将url替换并且不刷新页面,好比挂羊头卖狗肉,http并没有去请求服务器该路径下的资源,一旦刷新就会暴露这个实际不存在的“羊头”,显示404。

那么如何去解决history模式下刷新报404的弊端呢,这就需要服务器端做点手脚,将不存在的路径请求重定向到入口文件(index.html),前后端联手,齐心协力做好“挂羊头卖狗肉”的完美特效。

总之,pushState方法不会触发页面刷新,只是导致history对象发生变化,地址栏会有反应。

history模式下,build之后本地 index.html 打开是无效的。

hash模式下,build之后本地 index.html 打开正常!

如何解决SPA应用首屏加载过慢

  • 将全局引入转换为按需引入文件

  • 在 config/index.js 文件中将productionSourceMap 的值设置为false. 不生成映射资源

  • 路由懒加载:懒加载即组件的延迟加载,通常vue的页面在运行后进入都会有一个默认的页面,而其他页面只有在点击后才需要加载出来,使用懒加载可以将页面中的资源划分为多份,从而减少第一次加载的时候耗时

    这种优化,就是将每个组件的js代码独立出来,在使用到这个组件时,才向服务器请求文件,并且请求过一次后就会缓存下来,再次使用到这个组件时,就会使用缓存,不再发送请求

  • 压缩css和js文件

  • 使用cdn托管(就是把原服务器上数据复制到其他服务器上,用户访问时,哪台服务器近访问到的就是哪台服务器上的数据。)

ES6

var,let,const之间的区别

var声明变量可以重复声明,而let不可以重复声明

var是不受限于块级的,而let是受限于块级

var会与window相映射(会挂一个属性),而let不与window相映射

var可以在声明的上面访问变量,而let有暂存死区,在声明的上面访问变量会报错

const声明之后必须赋值,否则会报错

const定义不可变的量,改变了就会报错

const和let一样不会与window相映射、支持块级作用域、在声明的上面访问变量会报错

解构赋值

数组解构
let [a, b, c] = [1, 2, 3]   //a=1, b=2, c=3
let [d, [e], f] = [1, [2], 3]    //嵌套数组解构 d=1, e=2, f=3
let [g, ...h] = [1, 2, 3]   //数组拆分 g=1, h=[2, 3]
let [i,,j] = [1, 2, 3]   //不连续解构 i=1, j=3
let [k,l] = [1, 2, 3]   //不完全解构 k=1, l=2
对象结构
let {a, b} = {a: 'aaaa', b: 'bbbb'}      //a='aaaa' b='bbbb'
let obj = {d: 'aaaa', e: {f: 'bbbb'}}
let {d, e:{f}} = obj    //嵌套解构 d='aaaa' f='bbbb'
let g;
(g = {g: 'aaaa'})   //以声明变量解构 g='aaaa'
let [h, i, j, k] = 'nice'    //字符串解构 h='n' i='i' j='c' k='e'
函数参数的定义

一般我们在定义函数的时候,如果函数有多个参数时,在es5语法中函数调用时参数必须一一对应,否则就会出现赋值错误的情况,来看一个例子:

function personInfo(name, age, address, gender) {
console.log(name, age, address, gender)
}
personInfo('william', 18, 'changsha', 'man')

上面这个例子在对用户信息的时候需要传递四个参数,且需要一一对应,这样就会极易出现参数顺序传错的情况,从而导致bug,接下来来看es6解构赋值是怎么解决这个问题的:

function personInfo({name, age, address, gender}) {
  console.log(name, age, address, gender)
}
personInfo({gender: 'man', address: 'changsha', name: 'william', age: 18})

这么写我们只知道要传声明参数就行来,不需要知道参数的顺序也没关系

变换变量的值

在es5中我们需要交换两个变量的值需要借助临时变量的帮助,来看一个例子:

var a=1, b=2, c
c = a
a = b
b = c
console.log(a, b)

来看ES6如何实现

let a=1, b=2;
[b, a] = [a, b]
console.log(a, b)
函数默认参数

在日常开发中,经常会有这种情况:函数的参数需要默认值,如果没有默认值在使用的时候就会报错,来看es5中是怎么做的:

function saveInfo(name, age, address, gender) {
name = name || 'william'
age = age || 18
address = address || 'changsha'
gender = gender || 'man'
console.log(name, age, address, gender)
}
saveInfo()

在函数离 main先对参数做一个默认值赋值,然后再使用避免使用的过程中报错,再来看es6中的使用的方法:

function saveInfo({name= 'william', age= 18, address= 'changsha', gender= 'man'} = {}) {
  console.log(name, age, address, gender)
}
saveInfo()

forEach,for in,for of三者的区别(待补充)

forEach更多的用来遍历数

for in 一般常用来遍历对象或json

for of数组对象都可以遍历,遍历对象需要通过和Object.keys()

for in循环出的是key,for of循环出的是value

使用箭头函数应该注意什么?(待补充)

1、用了箭头函数,this就不是指向window,而是父级(指向是可变的)
2、不能够使用arguments对象
3、不能用作构造函数,这就是说不能够使用new命令,否则会抛出一个错误
4、不可以使用yield命令,因此箭头函数不能用作 Generator 函数

Set、Map的区别

应用场景Set用于数据重组,Map用于数据储存

Set:
1,成员不能重复
2,只有键值没有键名,类似数组
3,可以遍历,方法有add, delete,has

Map:
1,本质上是健值对的集合,类似集合
2,可以遍历,可以跟各种数据格式转换

promise对象的用法,手写一个promise(待补充)

promise是一个构造函数,下面是一个简单实例

var promise = new Promise((resolve,reject) => {
    if (操作成功) {
        resolve(value)
    } else {
        reject(error)
    }
})
promise.then(function (value) {
    // success
},function (value) {
    // failure
})

Ajax

Github

webpack

微信小程序

网络协议

性能优化

你可能感兴趣的:(Vue,前端,知识点)