VUE常见知识点

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

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

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

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

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

  • 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:可以写一个确认停止事件的确认框。

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

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

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

三种

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

5、Vue组件间的参数传递

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

2、v-model

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

// 父组件

{{msg}}

data(){ return{ msg:'model' } } // 子组件 props: ['value'], methods: { toInput(e){ this.$emit('input', e.target.value) } }

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

// 父组件

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

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

// 父组件

 
data(){
    return {
        num: 0
    }
}
// 子组件
add
data(){ return { counter: this.count } }, props: ["count"], methods: { handleAdd(){ this.$emit('update:count', ++this.counter) } }

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

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

三、任意组件
可以用Vuex或Event Bus解决
eventBus的使用
1.新建一个bus.js文件

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

2.使用它

添加
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) }) } }

6、什么是vue的计算属性

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

7、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 依赖的页面。”

8、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。

9、vue路由的钩子函数

首页可以控制导航跳转,beforeEach,afterEach等,一般用于页面title的修改。一些需要登录才能调整页面的重定向功能。

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

10、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,使得结构非常清晰,方便管理。

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

11、组件中data什么时候可以适用对象

组件复用时所有组件实例都会共享data,如果data是对象就会造成一个组件修改data以后会影响到其他所有组件,所以需要将data写成函数,每次用到就调用一次函数获得新的数据
当我们使用new Vue()的方式的时候,无论我们将data设置为对象还是函数都是可以的,因为new Vue()的方式是生成一个根组件,该组件不会复用,也就不存在共享data的情况

12、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性能更好一点

13、怎么定义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 

14、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
	    }
	}
	
//利用计算属性的特性来实现,当依赖改变时,便会重新计算一个新值。

15、前端如何优化网站性能

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

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

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

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

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

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

18、vue的优点是什么?

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

二、可重用性。你可以把一些视图逻辑放在一个ViewModel里面,让很多view重用这段视图逻辑。

三、独立开发。开发人员可以专注于业务逻辑和数据的开发(ViewModel),设计人员可以专注于页面设计。

四、可测试。界面素来是比较难于测试的,而现在测试可以针对ViewModel来写。

19、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 - (完成)响应内容解析完成,可以在客户端调用了

 

你可能感兴趣的:(Vue)