目录
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', '小红')
},
},
怎样理解 Vue 的单向数据流?
所有的 prop 都使得其父子 prop 之间形成了一个单向下行绑定:父级 prop 的更新会向下流动到子组件中,但是反过来则不行。
这样会防止从子组件意外改变父级组件的状态,从而导致你的应用的数据流向难以理解。
额外的,每次父级组件发生更新时,子组件中所有的 prop 都将会刷新为最新的值。这意味着你不应该在一个子组件内部改变 prop。如果你这样做了,Vue 会在浏览器的控制台中发出警告。
子组件想修改时,只能通过 $emit 派发一个自定义事件,父组件接收到后,由父组件修改。
有两种常见的试图改变一个 prop 的情形 :
- 这个 prop 用来传递一个初始值;这个子组件接下来希望将其作为一个本地的 prop 数据来使用。 在这种情况下,最好定义一个本地的 data 属性并将这个 prop 用作其初始值:
props: ['initialCounter'],
data: function () {
return {
counter: this.initialCounter
}
}
- 这个 prop 以一种原始的值传入且需要进行转换。 在这种情况下,最好使用这个 prop 的值来定义一个计算属性
props: ['size'],
computed: {
normalizedSize: function () {
return this.size.trim().toLowerCase()
}
}
vue 通信有哪几种方式?
(1)props / $emit 适用 父子组件通信
- 这种方法是 Vue 组件的基础,相信大部分同学耳闻能详,所以此处就不举例展开介绍。
(2) ref 与 $parent / $children 适用 父子组件通信
- ref:如果在普通的 DOM 元素上使用,引用指向的就是 DOM 元素;如果用在子组件上,引用就指向组件实例
- $parent / $children:访问父 / 子实例
(3)EventBus ($emit / $on) 适用于 父子、隔代、兄弟组件通信
- 这种方法通过一个空的 Vue
- 实例作为中央事件总线(事件中心),用它来触发事件和监听事件,从而实现任何组件间的通信,包括父子、隔代、兄弟组件。
(4)provide / inject 适用于 隔代组件通信
- 祖先组件中通过 provider 来提供变量,然后在子孙组件中通过 inject 来注入变量。provide / inject API主要解决了跨级组件间的通信问题,不过它的使用场景,主要是子组件获取上级组件的状态,跨级组件间建立了一种主动提供与依赖注入的关系。
(5)Vuex 适用于 父子、隔代、兄弟组件通信
- Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。每一个 Vuex 应用的核心就是 store(仓库)。“store”
- 基本上就是一个容器,它包含着你的应用中大部分的状态 ( state )。
- Vuex 的状态存储是响应式的。当 Vue 组件从 store 中读取状态的时候,若 store
- 中的状态发生变化,那么相应的组件也会相应地得到高效更新。
- 改变 store 中的状态的唯一途径就是显式地提交 (commit) mutation。这样使得我们可以方便地跟踪每一个状态的变化。
vue生命周期有那些?
beforeCreate:vue实例的挂载元素el和数据对象data都是undefined,还没用初始化
created:vue实例的数据对象data有了,可以访问里面的数据和方法,未挂载到DOM,el还没有
beforeMount:vue实例的el和data都初始化了,但是挂载之前未虚拟DOM节点
mounted:vue实例挂载到真实DOM上,就可以通过DOM获取DOM节点
beforeupdated:响应式数据更新时调用,发生在虚拟DOM打补丁之前,适合在更新之前访问现有的DOM,比如手动一处已添加的事件监听器
updated:虚拟DOM重新渲染和打补丁之后调用,组成新的DOM已经更新,避免在这个钩子函数中操作数 据,防止死循环
beforeDestroy:实例销毁前调用,实例还可以用,this能获取到实例,常用于销毁定时器,解绑事件
destroyed:实例销毁后调用,调用后所有事件监听器会被移除,所有的子实例都会被销毁
组件生命周期
- activated :keep-alive 组件激活时调用。该钩子在服务器端渲染期间不被调用
- deactivated :keep-alive 组件停用时调用。该钩子在服务器端渲染期间不被调用
- errorCaptured(2.5.0+ 新增) 当捕获一个来自子孙组件的错误时被调用。此钩子会收到三个参数:错误对象、发生 错误的组件实例以及一个包含错误来源信息的字符串,此钩子可以返回 false 以阻止该错误继续 向上传播
Vue中组件生命周期调用顺序
- 组件的调用顺序都是先父后子,渲染完成的顺序是先子后父。
- 组件的销毁操作是先父后子,销毁完成的顺序是先子后父。
加载渲染过程
- 父beforeCreate->父created->父beforeMount->子beforeCreate->子created->子beforeMount- >子mounted->父mounted
子组件更新过程
- 父beforeUpdate->子beforeUpdate->子updated->父updated
父组件更新过程
- 父 beforeUpdate -> 父 updated
销毁过程
- 父beforeDestroy->子beforeDestroy->子destroyed->父destroyed
第一次页面加载会触发哪几个钩子?
第一次页面加载时会触发 beforeCreate, created, beforeMount, mounted 这几个钩子
Vue 中 computed 和 watch 有什么区别?
计算属性 computed:
- 支持缓存,只有依赖数据发生变化时,才会重新进行计算函数;
- 计算属性内不支持异步操作;
- 计算属性的函数中都有一个 get(默认具有,获取计算属性)和 set(手动添加,设置计算属性)方法;
- 计算属性是自动监听依赖值的变化,从而动态返回内容。
侦听属性 watch:
- 不支持缓存,只要数据发生变化,就会执行侦听函数;
- 侦听属性内支持异步操作;
- 侦听属性的值可以是一个对象,接收 handler 回调,deep,immediate 三个属性;
- 监听是一个过程,在监听的值变化时,可以触发一个回调,并做一些其他事情。
路由跳转(导航)
声明式导航
- <router-link to="/index">前往首页</router-link>
编程式导航
- this.$router.push("/search") 是添加了新的历史记录
- this.$router.replace("/search") 是使用新的记录替换当前记录
router和route的区别
- router为VueRouter的实例,相当于一个全局的路由器对象,里面包含所有路由的对象和属性,例如history对象。。。经常用的跳转链接就可以用this.$router.push,和router-link跳转一样。
- route是一个跳转的路由对象。可以认为是当前组件的路由管理,指当前激活的路由对象,包含当前url解析得到的数据,可以从对象里获取一些数据。如name,path等
vue中fullPath和path的区别
fullPath:是路由全地址,包括连接携带的参数,如:192.168.0.1/index?page=1,fullPath为/index?page=1
path:是路径,不带参数,如:192.168.0.1/index?page=1,path为/index
Vue循环的key作用
- Key值的存在保证了唯一性
- 提高列表渲染性能,尽量减少DOM操作
- Vue在执行时,会对节点进行检查,如果没有key值,那么vue检查到这里有dom节点,就会对内容清空并赋新值,如果有key值存在,那么会对新老节点进行对比,比较两者key是否相同,进行调换位置或删除操作
vue跨域的解决方式
- 1.后台更改header
- 2.使用jq提供jsonp
- 3.用http-proxy-middleware(配置代理服务器的中间件)
在Vue中如何操作DOM
- 要在mounted中使用,因为只有在执行mounted的时候,vue已经渲染了dom节点,这个时候是可以获取dom节点的,vue中尽量不去操作dom元素,选用ref操作属性获取
-
<button ref="btn">获取ref</button> this.$refs.btn.style.backgroundColor="#ff0000" mounted(){//这里必须是mouted钩子 this.title = document.querySelector('#footer-box-title'); this.title.style.color = "#ff0000"; }
$nextTick是干什么的
在下次 DOM 更新循环结束之后执行延迟回调。在修改数据之后立即使用这个方法,获取更新后的 DOM。
this.$nextTick (()=>{ })可以在mounted之前的生命周期中操作dom