前端面试题

338 阅读26分钟

1.css3新特性

 -   border-radius:创建圆角边框
 -   box-shadow:为元素添加阴影
 -   border-image:使用图片来绘制边框
 -   background-size:背景图片大小
 -   transition:过渡
 -   animation:动画
 渐变 
 flex布局

2.css优先级

!important<内联 > ID > 类、伪类、属性选择器 > 标签 >通配符

3.px,vw/vh,rem的区别

px, 表示像素,所谓像素就是呈现在我们显示器上的一个个小点,每个像素点都是大小等同的, 
     所以像素为计量单位被分在了绝对长度单位中
rem,相对单位,相对的只是HTML根元素`font-size`的值
vw ,就是根据窗口的宽度,分成100等份,100vw就表示满宽,50vw就表示一半宽。
     同理,`vh`则为窗口的高度

4.es6新特性

 symbol,表示独一无二的值,即每个symbol类型的值都不相同
 新加了俩了声明变量的关键词letconst
 解构赋值是对赋值运算符的扩展。它是一种针对数组或者对象进行模式匹配,然后对其中的变量进行赋值。
 assign用于浅拷贝源对象可枚举属性到目标对象
 扩展运算符 用于拷贝目标对象所有可遍历的属性到当前对象
 is方法和(===)功能基本类似,用于判断两个值是否绝对相等。
 biglnt 数据类型是为了让javascript程序能表示超出Number类型支持的数值范围,在等于大整数进行数学运算时
        以任意精度表示整数的能力尤为重要 有了biglnt整数溢出将不再是一个问题

5.如何理解响应式网站?

响应式网站是指能够适应不同设备和屏幕尺寸的网站。它通过使用灵活的布局、自适应的图片和媒体查询等技术,
    以确保在各种设备上都能提供最佳用户体验。
理解响应式网站可以从以下几个方面入手:
1.弹性布局:响应式网站使用弹性布局来适应不同屏幕尺寸。相对于固定宽度的布局,
    弹性布局使用相对单位(如百分比)和流动的盒模型,使得网站的元素能够自动伸缩和调整大小,以适应屏幕的变化。
2.媒体查询:媒体查询是一种CSS3的功能,它可以根据不同的设备特性(如屏幕宽度、浏览器窗口大小等)来应用不同的样式。
    通过媒体查询,可以为不同的屏幕尺寸定义不同的布局和样式,使得网站在各种设备上都能呈现最佳的展示效果。
3.自适应图片:在响应式网站中,图片也是需要适应不同屏幕尺寸。通过使用CSS max-width属性、picture元素、srcset属性等技术,
    可以为不同设备提供适当大小的图片,以避免加载过大的图片、提高网站加载速度并节省带宽。
4.视口设置:视口是指浏览器中用于显示网页内容的区域。
    在响应式网站中,通过设置视口的meta标签(如viewport),可以控制网页如何在移动设备上进行缩放和布局。
    通过设置合适的视口参数,可以让网站在移动设备上呈现好的可读性和用户体验。
总之,响应式网站是一种能够根据不同设备和屏幕尺寸自适应展示的网站。通过使用弹性布局、媒体查询、自适应图片和视口设置等技术,
    可以使网站在不同设备上都能提供优良的用户体验。

6.闭包

 a.怎么理解闭包 
   闭包指有权访问另一个函数作用域中变量的函数。简单理解就是一个作用域可以访问另一个函数内部的局部变量
 b.闭包的作用
   封闭数据 实现数据私有 外部也可以访问函数内部的变量
   闭包很有用 因为他运行将函数与其所操作的某些数据(环境)关联起来
 c.优缺点
   优点:
   延长变量作用域 在函数的外部可以访问函数内部的局部变量
   缺点:
   容易造成内层泄漏,因为闭包中的局部变量永远不会被回收 解决方法:需要手动清除 把变量变为null
 d.概念
   一个函数对周围状态的引用捆绑在一起,闭包让开发者可以从内部函数访问外部函数的作用域
 e.闭包是指函数嵌套时, 内层函数访问外层函数的局部变量
 总结:
   1. 一旦发生闭包, 意味着外层函数的局部变量不会随着函数的结束而释放, 会长期存在一个叫 closure (闭包)的空间中
   2. 闭包会导致内存泄漏, 但这种内存泄漏是必要的, 我们无法阻止的, 只能说尽量少用闭包, 但必须用的时候还是得用

7.原型和原型链

  原型:js的每个函数在创建的时候,都会生成一个属性prototype,
    这个属性指向一个对象,这个对象就是函数的原型对象,该原型对象中有个属性为constructor,
  指向该函数,这样原型对象和他的函数直接就产生了联系
  原型链:当访问一个对象的某个属性时,会先在这个对象本身属性上查找,
    如果没有找到,则会去它的__proto__隐式原型上查找,
  即它的构造函数的prototype,如果还没有找到就会再在构造函数的prototype的__proto__中查找,
  这样一层一层向上查找就会形成一个链式结构,我们称为原型链
复制代码

8.js继承

 JavaScript 对象是动态的属性(指其自有属性)“包”。
 JavaScript 对象有一个指向一个原型对象的链。
 当试图访问一个对象的属性时,它不仅仅在该对象上搜寻,还会搜寻该对象的原型,
 以及原型的原型,依次层层向上搜索,直到找到一个名字匹配的属性或到达原型链的末尾

9.如何用css画一个三角形

    先设置1个盒子 给出边框色和边框宽度
    再给边框宽度增加 设置border边四个颜色
    然后给盒子的宽高给0 再消除掉其他的三个边颜色 此时就能得到一个三角形

10.如何拓展数组的方法

    给数组(Array)对象添加一个原型对象名叫max,并且给这个叫max的原型对象设置一个方法。
   但是方法里操作的数据不能写死,而应该谁调用就用谁的数据,所以也就是说要用this

Array.prototype.max = function (){
let max = this[0]
//先取出调用这个方法的数组的第一个元素
for(let i = 1; i <this.length ; i++){
if(this[i] >max){
max = this[i]
   }
  }
  //把最大值返回
  return max
}
let arr1 = [1,2,3]
let arr2 = [10,20,30]

let res1 = arr1.max()
let res2 = arr2.max()
console.log(res1) //3
console.log(res2) //30

这样,就在Array里设置好了一个叫max的原型对象,由于所有数组都属于Array对象,
所以任意一个数组都能通过原型链的方式找到这个叫max的原型对象,并调用该方法

11.数组的常见方法?

1.push 
定义:向数组的末尾追加元素 
    @params:追加的项(多个任意类型)
    @return:新增数组的长度
    是否改变原数组:改变
2.unshift   
定义:向数组的开头增加元素
    @params:追加的项(多个任意类型)
    @return:新增数组的长度
    是否改变原数组:改变
3.shift
定义:删除数组的开头项
    @params:无
    @return:删除的那一项
    是否改变原数组:改变
4.pop
定义:删除数组的结尾项
    @params:无
    @return:删除的那一项
    是否改变原数组:改变
5.splice
定义:实现数组的增加、删除、修改;
    @params:n,m,x
    @return:修改后的新数组
    是否改变原数组:改变
6.slice
定义:实现数组的查询
    @params:n,m //从索引n开始,找到索引为m的地方(不包含m这一项)
    @return:把找到的内容以新数组的形式返回
    是否改变原数组:不改变
7.concat
定义:实现数组拼接(合并)
    @params:拼接的项(多个任意值)
    @return:拼接后的新数组
    是否改变原数组:不改变
8.toString
定义:把数组转换为字符串
    @params:无
    @return:转换后的字符串,每一项用逗号分隔
    是否改变原数组:不改变
 9.join
 定义:把数组转换为字符串
    @params:按指定的分隔符连接
    @return:转换后的字符串
    是否改变新数组:不改变

12.如何判断数据类型

  a.可以根据typeof运算符来看返回类型,但是typeof只能用来判断简单(值)类型的,
  不能用来判断引用类型

  列如:
  let a  = 8
  console.log(typeof a )//numbder
  在控制台上面的结果是number 说明是数值 以此类推

b.通过tostring来判断
   通过objcet原型链(prototype)上的toString来判断变量的类型
是最直接靠谱的这也是各大 框架底层用来判断数据类型的方法

    let a = 8 
    let b = '8' 
    let c = true 
    let d = [1,2,3,4,5] 
    let e ={id:1,name:'15'}
    let f =undefined 
    myTypeof(a)//number 
    myTypeof(b)//string 
    myTypeof(c)//boolean
    myTypeof(d)//Array
    myTypeof(e)//object
    myTypeof(f)//undefined 
    function myTypeof(obj){ console.log(Object.prototype.toString.call(obj)) }

13.var, let和const的区别

1.var 声明的变量可以`重复声明`,letconst不可以;
2.var 声明的变量会`提升到当前作用域的最前面`,letconst不会;
3.var声明的变量会`挂载到window上`,成为window的属性,letconst不会;
4.letconst会产生`块级作用域`,var不会
5.letconst存在`暂时性死区`(声明之前不能调用),var没有  
针对cosnt声明的变量:
6.cosnt 声明时,`必须赋值`,否则会报错,  
这是因为const声明的变量在初始化之后就不能再次赋值,因此必须在声明时赋值。
7.cosnt声明的是常量,`不能更改`,  
指的是基本数据类型不能更改值,而引用数据类型不能更改他的引用地址,
这意味着无法通过赋值语句来更改常量的值,但是如果const声明的变量是一个对象或数组,
则仍然可以更改其属性或元素的值。

14.defineproperty 和 Proxy

defineproperty 只能监听某个属性而不能监听整个对象 
proxy 不用设置具体属性,直接监听整个对象 
defineproperty 监听需要知道是哪个对象的哪个属性
而 proxy 只需要知道哪个对象就可以了
也就是会省去 for in 循环提高了效率

15.防抖和节流

 防抖和节流都是用来提升浏览器性能的优化手段,他们的区别在于:
 防抖:在单位时间内频繁的触发事件 只会执行最后一次
 应用场景:实时搜索(keyup) 、 拖拽(mousemove)
 节流:在单位时间内频繁的触发事件 只会执行一次
 应用场景:窗口调整(resize)、页面滚动(scroll)、抢购和疯狂点击(mousedown)、

16.箭头函数

 箭头函数是Es6新增的一种定义函数表达式的语法,它简化了我们之前写的函数书写方式,
 箭头函数实例化的函数对象与我们Es5之前创建的函数表达式的创建函数行为是相同的。在任何使用函数表达式的地方,
 都可以使用箭头函数。

     //Es5
    let sum = function(a,b){
        return a + b;
    }
    // Es6
    let sum1 = (a,b) =>{
        return a + b;
    }
    console.log(sum(1,2));//3
    console.log(sum1(1,2));//3

 可以看到我们少写了function,如果我们只传递一个参数还可以把小括号去掉
 直接写 let sum1 = a =>{} 也可以运行

17.重绘和回流

什么是回流:
      当我们对DOM的修改引发了DOM几何尺寸的变化(比如修改元素的宽、高或隐藏元素等)时,
      浏览器需要重新计算元素的几何属性(其他元素的几何属性和位置也会因此受到影响),
      然后再将计算机的结果绘制出来。这个过程就是回流(也叫重排)
由本身的大小宽高改变,引发局部或全局的排班,会引发回流或局部回流
   全局范围:  从根节点html开始对整个渲染树进行重新布局
   局部范围: 对渲染树的某部分或某一个渲染对象进行重新布局
 什么是重绘:
     我们对DOM的修改导致了样式的变化,却并未影响其几何属性(比如修改颜色或背景色)时
     浏览器不需要重新计算元素的几何属性,直接为该元素绘制新的样式。这个过程叫做重绘
     只改变外观、风格、不影响布局、会引发重绘
  回流比重绘大
     重绘:某些元素的外观被改变,列如:元素的填充颜色
     回流:重新生成布局,重新排列元素
 局部范围重排:
     用局部布局来解释这种现象,把一个DOM的宽高之类的几何信息定死,然后在DOM内部重排
     就只会重新渲染该dOM内部的元素,而不会影响到外界。
     就如上面的概念一样,单单改变元素的外观,肯定不会引起网页的重新生成布局,
     之后,将会重新绘制受到这次重排影响的部分
  一句话概括:回流必将引起重绘、重绘不一定会引起回流                

18. 递归函数

  递归:如果一个函数在内部可以调用其本身,那么这个函数就是递归函数。
        简单理解函数内部调用自己,这个函数就是递归函数
  优点:结构清晰,可读性强 需要有结束条件 return
  缺点:效率低,调用栈可以会溢出,其实每一个函数调用会在内存栈中分配空间,
       而且每个进程的栈的容量是有限的,当调用的层数太多时,就会超出栈的容量,从而导致栈溢出性能

19.微任务和宏任务

  首先因为Javascript是一门单线程的语言,意味着同一时间内只能做一件事,
      但是着并不意味着单线程就是阻塞,而实现单线程非阻塞的方法就是事件循环
  在JavaScript中所有的任务都可以分为
      同步任务:立即执行的任务,同步任务一般会直接进入到主线程中执行
      异步任务:异步执行的任务,比如ajax1网络请求,setimeout定时函数等
  在异步任务中又分为微任务和宏任务
      微任务:
        一个需要异步执行的函数,执行时机是在主函数执行结束之后,当前宏任务结束之前
        常见的微任务有:
        Promise.then
        MutaionObserver
        object.observe
        process.nextTick(node.js)
      宏任务:
        可以理解是每次执行的代码就是一个宏任务(包括每次从事件队列中获取一个事件回调并方到执行栈中执行)
        常见的宏任务有:
        script(可以理解为外层同步代码)
        setTimeout/setlnterval
        ul rendering/ul事件
        postMessage,MessageChannel
        setlmmediate

20.eventloop

    由于js是单线程的,一次只能执行一个任务。 那么多个任务堆在一起时,
       就要这些任务排排队。按照先进先出的规则,形成一条 消息队列
    多个任务源,形成多条 消息队列 这就形成一条事件循环的执行队列。 
    事件循环:
       就是一个执行消息队列的机制。 首先选择 优先级最高的

21.v-show和v-if

    首先v-show和v-if都是用来控制元素显示和隐藏的,但是其中的原理和使用方法也有差别
    v-show隐藏是为该元素添加display:none,元素还在
    v-if隐藏是将元素中的某个节点删除
    一般来说v-if有更高的切换开销,而且v-show有更高的初始渲染开销。因此,如果需要非常频繁的切换,
    则使用v-show较好,如果在运行时条件很少改变,则使用v-if较好

22.key的作用

    key的作用
        提升diff算法效率,因为diff算法需要进行节点的对比,早期如果不设置key的值的话
        它是一个undefined,现在会自动生成一个唯一值,但是你不管是没设置key,或者key值是索引来表示的话,
        它们的key值还是一样的,它的效率会降低,如果你设置了唯一值的话,在比较两个虚拟dom是不是一样的时候
        它首先会看你的key值是不是一样的,如果不一样它就会跳过
        设置key就是唯一标识
        主要是为了更高效的更新虚拟DOM,因为它可以非常精确的找到相同节点,因此patch过程会非常高效
        vue在patch过程中会判断俩个节点是不是相同节点时u,key是一个必要条件。
        比如渲染列表时,如果不写key,Vue在比较的时候,就可能会导致频繁更新元素,使整个Patch过程比较低效,影响性能
    如果用index作为下标的话会出现什么
        key的值不是唯一的话可能会导致上面图中表示的bug,使vue无法区分其他,
        还有比如在使用相同标签元素过渡切换的时候,就会导致只替换内部属性而不会触发过渡效果
        从源码里可以知道,Vue判断俩个节点是否相同主要判断两者的元素类型和Key等,
        如果不设置Key就可能永远让这俩个是相同节点,只能去做更新操作,
        就造成大量不必要的DOM更新操作,明显是不可取的
    

23.虚拟dom

       vue1是没有虚拟dom的,是vue2新出来的新特效,解决了跨平台的问题,不仅可以在浏览器运行,还可以在ios,安卓手机端运行
       没有虚拟dom的话,这是没有方法实现的,比如修改了一个数据,虚拟dom会重新生成
       但是虚拟dom最终会变成什么样子,这得由平台方去决定,虚拟dom其实就是一个对象,他有个属性,有键值对
       但是怎么把对象表示的含义变成真正的元素,这是个由平台决定的,这就是虚拟dom1最大的好处

24.diff算法

       跟虚拟dom配套出来的,也就是意味着不会去操作真实dom,diff算法的目的就是找出新旧不同虚拟dom之间的差异
       使最小化的更新视图,他是交叉比较,他判断节点是使用一个api,singweload 比较的条件就是key值
       这就是为什么在做虚拟循环的时候脚手架会让我们要加key1的值,这也是为了diff算法更加的方便
       difference(全拼)提升效率,它一定要用递归去比较

25.hash路由和history路由

   hash
      vue-router默认为hash模式,使用URl的hash来模拟一个完整的URL,当URL改变时,
       页面不会重新加载;#就是hash符号,中文名为哈希符或者锚点,在hash符号后的值称为hash值。
    路由的hash模式是利用了window 可以监听 onhashchange 事件来实现的,
      也就是说hash值是用来指导浏览器动作的,对服务器没有影响,HTTP 请求中也不会包括hash值,
    同时每一次改变hash值,都在浏览器的访问历史中增加一个记录,使用“后退”按钮,就可以回到上个位置
       所以,hash模式是根据hash值来发生改变,根据不同的值,渲染指定DOM位置的不同数据。
   优点:
    url中带一个#号
    可以改变URL,但不会触发页面重新加载(hash的改变会记录在  window.hisotry  中)因此并不算是一次 HTTP 请求,
       所以这种模式不利于 SEO 优化
    只能修改#后面的部分,因此只能跳转与当前URL同文档的 URL
    只能通过字符串改变 URL
    通过window.onhashchange监听hash的改变,借此实现无刷新跳转的功能。
    每改变一次hash(window.location.hash),都会在浏览器的访问历史中增加一个记录。
    路径中从#开始,后面的所有路径都叫做路由的`哈希值`并且哈希值它不会作为路径的一部分随着 http 请求,
    发给服务器
   History:
    history  是路由的另一种模式,在相应的router配置时将mode设置为  history  即可。
    history  模式是通过调用  window.history对象上的一系列方法来实现页面的无刷新跳转。
   利用了 HTML5 History Interface中新增的ushState()和replaceState()方法。
  这两个方法应用于浏览器的历史记录栈,在当前已有的back、forward、go的基础之上,
    它们提供了对历史记录进行修改的功能。只是当它们执行修改时,虽然改变了当前的 URL,但浏览器不会向后端发送请求。

27.nextTick

    页面的DOM还未渲染,这时候也没办法操作DOM,如果想要操作DOM。需要使用nextTick来解决这个问题
    实现原理:
      nextTick的核心是利用了如Promise MutaionObserver Setlmmediate setTimeout的原生Javascript
      方法来模拟对应的微/宏任务的实现,本质是为了利用javascript的这些异步回调任务队列
      来实现Vue框架中自己的异步回调队列
    Vue在更新DOM时是异步执行的。当数据发生变化,Vue将开启一个异步更新队列,视图需要等队列中所有数据变化完成之后,再统一更新
    应用场景:
     1.一个输入框本来是隐藏的,想让他显示的同时获取焦点
     2.在数据变化后执行的某个操作,而这个操作需要使用数据变化而变化的DOM结构的时候,这个操作就需要方法在的回调函数中
     3.在vue生命周期中,如果在created()钩子进行dom操作,也一定要放在的回调函数中

28.mixin的优点和缺点

    在导出的对象中可以写组件的配置项如:data methods computed watch
    作用:将组件内相同的业务逻辑提取到一个公共的模块,当组件内需要时再混入到组件内
    特性:
    1.要混入的对象中如果是生命周期函数 依次执行 先执行混入的生命钩子函数
    2.要混入的对象中的data 如果变量的值冲突 以组件内的值为准(覆盖)
    3.要混入的对象中methods 如果函数名冲突,以组件内的值为准(覆盖)
   优点:
   可以组件复用
   缺点:
   不可知 不易维护
       因为在mixins里面几乎可以加任何代码 props data methods 各种东西 
       就导致如果不了解mixins封装的代码话 是很难维护的

30.eventBus的原理?

  EventBus是一种事件发布/订阅模式的实现,它用于解耦不同组件之间的通信,使得组件能够松散地耦合并提高代码的可维护性。
EventBus的原理如下:
1.注册和订阅:组件可以通过订阅特定的事件来表明自己对该事件感兴趣。
    在EventBus中,组件需要将自己注册到EventBus,并指定要订阅的事件类型。
2.发布和通知:当某个组件发生了特定的事件,它可以将该事件发布到EventBus中。
    EventBus会根据事件的类型,通知所有订阅了该事件的组件。
3.事件分发:EventBus会维护一个事件注册表,其中记录了每个事件类型所对应的订阅组件列表。
    当事件发布时,EventBus会遍历相应事件类型的注册表,依次通知所有订阅组件。
4.异步处理:EventBus可以支持异步事件处理,即事件发布和订阅是非阻塞的。这意味着事件发布后,
     发布方可以继续执行其他任务,而不需要等待所有订阅组件完成处理。
总结起来,EventBus的原理就是通过组件的注册和订阅,以及事件的发布和通知,实现组件间解耦的事件通信机制。
     它能够提高代码的可维护性,使得系统的各个组件能够更加松散地协作。

31.vue2生命周期

   vue的生命周期就是vue实例从创建到销毁的过程
     也就是从开始创建 初始化数据 编译模板 挂载dom->渲染 更新 渲染 准备销毁 销毁在等一系列过程
     vue的生命周期常见的主要分为四大阶段八个钩子函数
     a.创建前/后
         执行before create执行的时候 data和method还没初始化 只有一些vue默认的方法
         created执行的时候 data和method已经初始化完成可以操作了
     b.挂载前/后
         在before mount执行的时候 模板已经在内存中渲染好了 但是还没有真正的渲染到页面中去
         在mounted 执行的时候 将内存中渲染好的模板 真正的替换到浏览器中
     执行完mounted vue实例的初始化阶段已经结束 此时已经脱离创建阶段 进入执行阶段
     //运行阶段只有俩个周期函数 会根据data数据的改变执行0或者多次
     c.更新前/后
         在beforeupdate执行的时候 页面的数据还是旧的 但是data的数据已经是最新的,页面还没和data保存同步
         在updated执行的时候 已经把更新后的数据渲染到视图中了 页面的数据已经是最新的了 和data保持同步
     //从运行阶段进入销毁阶段
     d.销毁前/后
         在beforeDestroy执行的时候 实例进入准备销毁的阶段 此时data methods 指令等还是可用状态
         在destroyed执行的时候 实例已经完成销毁 此时data methods 指令等都不可用
     另外三个生命周期函数不常用
         keep-alive主要用于保留组件状态或避免重新渲染
         activated只有在keep-alive组件激活时调用
         deactivated只有在keep-alive组件停用时调用
         errorCapured当捕获一个来自子孙组件的错误时被调用 此钩子会收到三个参数
          错误对象 发生错误的组件实例以及一个包含错误来源信息的字符串,
          此钩子可以返回false已阻止错误继续传播

32.created和mounted的区别?

   created
       执行before create执行的时候 data和method还没初始化 只有一些vue默认的方法
       created执行的时候 data和method已经初始化完成可以操作了
   mounted
       在before mount执行的时候 模板已经在内存中渲染好了 但是还没有真正的渲染到页面中去
       在mounted 执行的时候 将内存中渲染好的模板 真正的替换到浏览器中
   执行完mounted vue实例的初始化阶段已经结束 此时已经脱离创建阶段,进入执行阶段
   区别:
       created是在组件实例一旦创建完成的时候立刻调用,这时候页面`dom`节点并未生成mounted
       是在页面`dom`节点渲染完毕之后就立刻执行的触发时机上created是比mounted要更早的两者相同点:
       都能拿到实例对象的属性和方法讨论这个问题本质就是触发的时机,
       放在mounted请求有可能导致页面闪动(页面dom结构已经生成),
       但如果在页面加载前完成则不会出现此情况建议:放在create生命周期当中

33.v-model和.sync

    v-model和.sync的共同点 都是语法糖 都可以实现父子组件中的数据的双向通信
    v-model和.sync的不共同点
    v-model:
     a.父组件的v-model=""子组件@(input,value)
     b.一个组件只能绑定一个v-model
     c.v-model针对更多的是最终操作结果是双向绑定的的结果,是value,是一种change操作
    .sync:
     a.父组件:my-prop-name.sync子组件@update:my-prop-name的模式来替代事件触发。
       实现父子组件间的双向绑定
     b.一个组件可以多个属性用.sync修饰符,可以同时双向绑定多个prop
     c..sync针对更多的是各种各样的状态,是状态的互相传递,是status,是一种update操作

34.组件之间的通信方式

a.父向子通信:在子组件的标签上通过自定义属性传递父组件的数据,子组件内部通过props接收父向子传递的数据
b.子向父通信:在子组件的标签上自定义事件,自定义事件的值是父组件的方法,在子组件内部通过this.#emit()方法触发事件
    第一个参数为自定义事件,第二个参数可以传递子组件的内部数据,此时父组件中的方法就可以执行了
c.兄弟组件通信:可以采取eventbus实现数据传递,但是这种方式我们在开发中基本不用,多组件共享数据都用的是vuex
d.后代组件通信:可以采取依赖注入的方式,在祖先组价中通过provide提供数据,在后代组件中通过inject接收数据
e.无关联系组件通信:在开发中我们都是使用的vuex

35.vuex

vuex是一个专为了Vue.js应用程序开发的状态管理模式。它采用集中存储管理应用的所有组件的状态,并以相应的规则保证
  状态,状态以一种可预测的方式发生变化
vuex的出现解决了
    a.多个组件共享状态时,单向数据流的简洁性很容易被破坏
    b.多个视图依赖于同一状态
    c.来自不同视图的行为需要变更同一状态
vuex中五个主要的成员
   state 是用来存储数据的
   mutations 是用来修改state中数据的方法
   actions 是用来处理一些异步操作数据的行为方法
   getters 有点类似于计算属性,是对state中的数据做了一些处理
   modules 是用来对复杂业务分模块的,每个模块也可以有state mutaions actions gettets

36.