VUE常见知识点

一、Vue的双向数据绑定原理是什么?

vue.js 是采用数据劫持结合发布者-订阅者模式的方式,经过Object.defineProperty()来劫持各个属性的setter,getter,在数据变更时发布消息给订阅者,触发相应的监听回调。javascript

      具体步骤:
第一步:须要observe的数据对象进行递归遍历,包括子属性对象的属性,都加上 setter和getter
这样的话,给这个对象的某个值赋值,就会触发setter,那么就能监听到了数据变化
第二步:compile解析模板指令,将模板中的变量替换成数据,而后初始化渲染页面视图,并将每一个指令对应的节点绑定更新函数,添加监听数据的订阅者,一旦数据有变更,收到通知,更新视图
第三步:Watcher订阅者是Observer和Compile之间通讯的桥梁,主要作的事情是:
一、在自身实例化时往属性订阅器(dep)里面添加本身
二、自身必须有一个update()方法
三、待属性变更dep.notice()通知时,能调用自身的update()方法,并触发Compile中绑定的回调,则功成身退。
第四步:MVVM做为数据绑定的入口,整合Observer、Compile和Watcher三者,经过Observer来监听本身的model数据变化,经过Compile来解析编译模板指令,最终利用Watcher搭起Observer和Compile之间的通讯桥梁,达到数据变化 -> 视图更新;视图交互变化(input) -> 数据model变动的双向绑定效果。css

二、请详细说下你对vue生命周期的理解?

总共分为8个阶段建立前/后,载入前/后,更新前/后,销毁前/后html

  • beforeCreate 建立前执行(vue实例的挂载元素$el和数据对象data都为undefined,还未初始化)
  • created 完成建立 (完成了data数据初始化,el还未初始化)
  • beforeMount 载入前(vue实例的$el和data都初始化了,但仍是挂载以前为虚拟的dom节点,data.message还未替换。)
  • mounted 载入后html已经渲染(vue实例挂载完成,data.message成功渲染。)
  • beforeUpdate 更新前状态(view层的数据变化前,不是data中的数据改变前)
  • updated 更新状态后
  • beforeDestroy 销毁前
  • destroyed 销毁后 (在执行destroy方法后,对data的改变不会再触发周期函数,说明此时vue实例已经解除了事件监听以及和dom的绑定,可是dom结构依然存在)

说一下每个阶段能够作的事情前端

  • beforeCreate:能够在这里加一个loading事件,在加载实例时触发。
  • created:初始化完成时的事件写这里,若是这里结束了loading事件,异步请求也在这里调用。
  • mounted:挂在元素,获取到DOM节点
  • updated:对数据进行处理的函数写这里。
  • beforeDestroy:能够写一个确认中止事件的确认框。

三、第一次页面加载会触发哪几个钩子

 beforeCreate, created, beforeMount, mounted 这几个钩子vue

四、vue-router 有哪几种导航钩子?

三种java

  1. 全局导航钩子(跳转前进行判断拦截)
    • router.beforeEach(to, from, next),
    • router.beforeResolve(to, from, next),
    • router.afterEach(to, from ,next)
  2. 组件内钩子
    • beforeRouteEnter
    • beforeRouteUpdate
    • beforeRouteLeave
  3. 单独路由独享组件
    • beforeEnter

五、Vue组件间的参数传递

  • 父组件向子组件传值:
    • 子组件在props中建立一个属性,用来接收父组件传过来的值;
    • 在父组件中注册子组件;
    • 在子组件标签中添加子组件props中建立的属性;
    • 把须要传给子组件的值赋给该属性
  • 子组件向父组件传值:
    • 子组件中须要以某种方式(如点击事件)的方法来触发一个自定义的事件;
    • 将须要传的值做为$emit的第二个参数,该值将做为实参传给响应事件的方法;
  • 在父组件中注册子组件并在子组件标签上绑定自定义事件的监听。
// 父组件
<div>
    <child :data="child" @send="getFromChild"></child>
</div>
 
data(){
    return{
        toChild: '大儿子',
        fromChild: ''
    }
},
methods: {
    getFromChild(val){
        this.fromChild=val
    }
}
// 子组件
<div @click="toParent">{{data}}</div>
 
props:[data],
methods: {
    toParent(){
        this.$emit('send', '给父亲')
    }
}

二、v-model

v-model实际上是props,emit的语法糖,v-model默认会解析成名为value的prop和名为input的事件jquery

// 父组件
<children v-model="msg"></children>
<p>{{msg}}</p>
 
data(){
    return{
        msg:'model'
    }
}
// 子组件
<input :value="value" @input="toInput" />
 
props: ['value'],
methods: {
    toInput(e){
        this.$emit('input', e.target.value)
    }
}

3.在父组件使用$children访问子组件,在子组件中使用$parent访问父组件

// 父组件
<child />
 
data(){
    return {
        msg: '父组件数据'
    }
},
methods: {
    test(){
        console.log('我是父组件的方法,被执行')
    }
},
mounted(){
    console.log(this.$children[0].child_msg); // 执行子组件方法
}
// 子组件
<div>{{$parent.msg}}</div>
 
data(){
    return{
        child_msg: '子组件数据'
    }
},
mounted(){
    // 子组件执行父组件方法
    this.$parent.test(); 
}

四、.sync方式
在vue1.x中是对prop进行双向绑定,在vue2只容许单向数据流,也是一个语法糖

// 父组件
<child :count.sync="num" />
 
data(){
    return {
        num: 0
    }
}
// 子组件
<div @click="handleAdd">add</div>
 
data(){
    return {
        counter: this.count
    }
},
props: ["count"],
methods: {
    handleAdd(){
        this.$emit('update:count', ++this.counter)
    }
}

2、兄弟组件通讯:能够经过查找父组件中的子组件实现,
this.$parent.$children
在$children中能够经过组件name查询到须要的组件实例,而后进行通讯
跨多层次组件通讯
可使用provide/inject,虽然文档中不推荐直接使用在业务中。
假设有父组件A,而后有一个跨多层次的子组件Bwebpack

// 父组件A
export default{
    provide: {
        data: 1
    }
}
// 子组件B
export default{
    inject: ['data'],
    mounted(){
        // 不管跨几层都能获取父组件的data属性
        console.log(this.data); // 1
    }
}

3、任意组件
能够用Vuex或Event Bus解决
eventBus的使用
1.新建一个bus.js文件web

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

2.使用它vue-router

<div @click="addCart">添加</div>
import Bus from 'bus.js';
export default{
    methods: {
        addCart(event){
            Bus.$emit('getTarget', event.target)
        }
    }
}
// 另外一组件
export default{
    created(){
        Bus.$on('getTarget', target =>{
            console.log(target)
        })
    }
}

六、什么是vue的计算属性

答:在模板中放入太多的逻辑会让模板太重且难以维护,在须要对数据进行复杂处理,且可能屡次使用的状况下,尽可能采起计算属性的方式。
好处:
①使得数据处理结构清晰;
②依赖于数据,数据更新,处理结果自动更新;
③计算属性内部this指向vm实例;
④在template调用时,直接写计算属性名便可;
⑤经常使用的是getter方法,获取数据,也可使用set方法改变数据;
⑥相较于methods,无论依赖的数据变不变,methods都会从新计算,可是依赖数据不变的时候computed从缓存中获取,不会从新计算。

七、Vue的路由实现:hash模式 和 history模式

hash模式:在浏览器中符号“#”,#以及#后面的字符称之为hash,用window.location.hash读取;
特色:hash虽然在URL中,但不被包括在HTTP请求中;用来指导浏览器动做,对服务端安全无用,hash不会重加载页面。
hash 模式下,仅 hash 符号以前的内容会被包含在请求中,如 http://www.xxx.com,所以对于后端来讲,即便没有作到对路由的全覆盖,也不会返回 404 错误。

history模式:history采用HTML5的新特性;且提供了两个新方法:pushState(),replaceState()能够对浏览器历史记录栈进行修改,以及popState事件的监听到状态变动。
history 模式下,前端的 URL 必须和实际向后端发起请求的 URL 一致,如 http://www.xxx.com/items/id。后端若是缺乏对 /items/id 的路由处理,将返回 404 错误。Vue-Router 官网里如此描述:“不过这种模式要玩好,还须要后台配置支持……因此呢,你要在服务端增长一个覆盖全部状况的候选资源:若是 URL 匹配不到任何静态资源,则应该返回同一个 index.html 页面,这个页面就是你 app 依赖的页面。”

八、Vue与Angular以及React的区别

1.与AngularJS的区别

相同点:
都支持指令:内置指令和自定义指令;都支持过滤器:内置过滤器和自定义过滤器;都支持双向数据绑定;都不支持低端浏览器。
 
不一样点:
AngularJS的学习成本高,好比增长了Dependency Injection特性,而Vue.js自己提供的API都比较简单、直观;在性能上,AngularJS依赖对数据作脏检查,因此Watcher越多越慢;Vue.js使用基于依赖追踪的观察而且使用异步队列更新,全部的数据都是独立触发的。

2.与React的区别

相同点:
React采用特殊的JSX语法,Vue.js在组件开发中也推崇编写.vue特殊文件格式,对文件内容都有一些约定,二者都须要编译后使用;中心思想相同:一切都是组件,组件实例之间能够嵌套;都提供合理的钩子函数,可让开发者定制化地去处理需求;都不内置列数AJAX,Route等功能到核心包,而是以插件的方式加载;在组件开发中都支持mixins的特性。

不一样点:
React采用的Virtual DOM会对渲染出来的结果作脏检查;Vue.js在模板中提供了指令,过滤器等,能够很是方便,快捷地操做Virtual DOM。

九、vue路由的钩子函数

首页能够控制导航跳转,beforeEach,afterEach等,通常用于页面title的修改。一些须要登陆才能调整页面的重定向功能。

beforeEach主要有3个参数to,from,next:
to:route即将进入的目标路由对象,
from:route当前导航正要离开的路由
next:function必定要调用该方法resolve这个钩子。执行效果依赖next方法的调用参数。能够控制网页的跳转。

十、vuex是什么?怎么使用?哪一种功能场景使用它?

只用来读取的状态集中放在store中; 改变状态的方式是提交mutations,这是个同步的事物; 异步逻辑应该封装在action中。
在main.js引入store,注入。新建了一个目录store,….. export 。
场景有:单页应用中,组件之间的状态、音乐播放、登陆状态、加入购物车
state
Vuex 使用单一状态树,即每一个应用将仅仅包含一个store 实例,但单一状态树和模块化并不冲突。存放的数据状态,不能够直接修改里面的数据。
mutations
mutations定义的方法动态修改Vuex 的 store 中的状态或数据。
getters
相似vue的计算属性,主要用来过滤一些数据。
action
actions能够理解为经过将mutations里面处里数据的方法变成可异步的处理数据的方法,简单的说就是异步操做数据。view 层经过 store.dispath 来分发 action。
modules
项目特别复杂的时候,可让每个模块拥有本身的state、mutation、action、getters,使得结构很是清晰,方便管理。

应用场景:单页应用中,组件之间的状态。音乐播放、登陆状态、加入购物车。

十一、组件中data何时能够适用对象

组件复用时全部组件实例都会共享data,若是data是对象就会形成一个组件修改data之后会影响到其余全部组件,因此须要将data写成函数,每次用到就调用一次函数得到新的数据
当咱们使用new Vue()的方式的时候,不管咱们将data设置为对象仍是函数都是能够的,由于new Vue()的方式是生成一个根组件,该组件不会复用,也就不存在共享data的状况

十二、v-if与v-show的用法与区别

  • vue中显隐方法经常使用两种,v-show和v-if,但这两种是有区别的。
  • 实现本质方法区别
    • vue-show本质就是标签display设置为none,控制隐藏
    • vue-if是动态的向DOM树内添加或者删除DOM元素
  • 编译的区别
    • v-show其实就是在控制css
    • v-if切换有一个局部编译/卸载的过程,切换过程当中合适地销毁和重建内部的事件监听和子组件
  • 编译的条件
    • v-show都会编译,初始值为false,只是将display设为none,但它也编译了
    • v-if初始值为false,就不会编译了
  • 性能
    • v-show只编译一次,后面其实就是控制css,而v-if不停的销毁和建立,故v-show性能更好一点

1三、怎么定义vue-router的动态路由?怎么获取传过来的动态参数?

在router目录下的index.js文件中,对path属性加上/:id。  使用router对象的params.id

页面配置 :to="路由/ :id=123"    获取参数使用  this.$route.params.id 

也可使用 Vue的get取值 页面配置     :to="路由?id=123"      获取参数  this.$route.query.id 

1四、Vue中如何监控某个属性值的变化

watch: {
      obj: {
      handler (newValue, oldValue) {
        console.log('obj changed')
      },
      deep: true
    }
  }
  
  // deep属性表示深层遍历,可是这么写会监控obj的全部属性变化,并非想要结果,修改以下:
  watch: {
	   'obj.a': {
	      handler (newName, oldName) {
	        console.log('obj.a changed')
	      }
	   }
  }
// 还有一种方法,能够经过computed来实现,只须要
computed: {
	    a1 () {
	      return this.obj.a
	    }
	}
	
//利用计算属性的特性来实现,当依赖改变时,便会从新计算一个新值。

1五、前端如何优化网站性能

1.减小 HTTP 请求数量
   	在浏览器与服务器进行通讯时,主要是经过 HTTP 进行通讯。浏览器与服务器须要通过三次握手,每次握手须要花费大量时间。并且不一样浏览器对资源文件并发请求数量有限(不一样浏览器容许并发数),	一旦 HTTP 请求数量达到必定数量,资源请求就存在等待状态,这是很致命的,所以减小 HTTP 的请求数量能够很大程度上对网站性能进行优化。
二、CSS Sprites:国内俗称 CSS 精灵,
   	这是将多张图片合并成一张图片达到减小 HTTP 请求的一种解决方案,能够经过 CSS background 属性来访问图片内容。这种方案同时还能够减小图片总字节数。
三、.合并 CSS 和 JS 文件:如今前端有不少工程化打包工具,
   	如:grunt、gulp、webpack等。为了减小 HTTP 请求数量,能够经过这些工具再发布前将多个 CSS 或者 多个 JS 合并成一个文件。
四、.采用 lazyLoad:俗称懒加载,能够控制网页上的内容在一开始无需加载,
   	不须要发请求,等到用户操做真正须要的时候当即加载出内容。这样就控制了网页资源一次性请求数量。
五、	控制资源文件加载优先级
   	浏览器在加载 HTML 内容时,是将 HTML 内容从上至下依次解析,
   	解析到 link 或者 script 标签就会加载 href 或者 src 对应连接内容,
   	为了第一时间展现页面给用户,就须要将 CSS 提早加载,
   	不要受 JS 加载影响。通常状况下都是 CSS 在头部,JS 在底部。
六、.利用浏览器缓存
   			浏览器缓存是将网络资源存储在本地,等待下次请求该资源时,
   			若是资源已经存在就不须要到服务器从新请求该资源,直接在本地读取该资源。
七、.减小重排(Reflow)
   			基本原理:重排是 DOM 的变化影响到了元素的几何属性(宽和高),
   			浏览器会从新计算元素的几何属性,会使渲染树中受到影响的部分失效,
   			浏览器会验证 DOM 树上的全部其它结点的 visibility 属性,
   			这也是 Reflow 低效的缘由。若是 Reflow 的过于频繁,CPU 使用率就会急剧上升。
八、.减小 Reflow,
   			若是须要在 DOM 操做时添加样式,
   			尽可能使用 增长 class 属性,而不是经过 style 操做样式。
   			减小 DOM 操做,图标使用 IconFont 替换

1六、网页从输入网址到渲染完成经历了哪些过程

大体能够分为以下7步:
   1.输入网址;
   2.发送到DNS服务器,并获取域名对应的web服务器对应的ip地址;
   3.与web服务器创建TCP链接;
   4.浏览器向web服务器发送http请求;
   5.web服务器响应请求,并返回指定url的数据(或错误信息,或重定向的新的url地址);
   6.浏览器下载web服务器返回的数据及解析html源文件;
   7.生成DOM树,解析css和js,渲染页面,直至显示完成;

1七、mvvmmvc区别?它和其它框架(jquery)的区别是什么?哪些场景适合?

mvc和mvvm其实区别并不大。都是一种设计思想。主要就是mvc中Controller演变成mvvm中的viewModel。mvvm主要解决了mvc中大量的DOM 操做使页面渲染性能下降,加载速度变慢,影响用户体验。

区别:vue数据驱动,经过数据来显示视图层而不是节点操做。
场景:数据操做比较多的场景,更加便捷

1八、vue的优势是什么?

1、低耦合。视图(View)能够独立于Model变化和修改,一个ViewModel能够绑定到不一样的"View"上,当View变化的时候Model能够不变,当Model变化的时候View也能够不变。

2、可重用性。你能够把一些视图逻辑放在一个ViewModel里面,让不少view重用这段视图逻辑。

3、独立开发。开发人员能够专一于业务逻辑和数据的开发(ViewModel),设计人员能够专一于页面设计。

4、可测试。界面素来是比较难于测试的,而如今测试能够针对ViewModel来写。

1九、vue.cli中怎样使用自定义的组件?有遇到过哪些问题吗?

第一步:在components目录新建你的组件文件(如:indexPage.vue),script必定要export default {}

第二步:在须要用的页面(组件)中导入:import indexPage from '@/components/indexPage.vue'

第三步:注入到vue的子组件的components属性上面,components:{indexPage}

第四步:在template视图view中使用,


例若有indexPage命名,使用的时候则index-page

20、XMLHttpRequest:XMLHttpRequest.readyState: 状态码的意思

0 - (未初始化)尚未调用send()方法

1 - (载入)已调用send()方法,正在发送请求

2 - (载入完成)send()方法执行完成,已经接收到所有响应内容

3 - (交互)正在解析响应内容

4 - (完成)响应内容解析完成,能够在客户端调用了