1、怎么理解mvvm这种设计模式
Model–View–ViewModel (MVVM) 是一个软件架构设计模式,是一种简化用户界面的事件驱动编程方式。 MVVM M Model 模型 指的是数据层 V View 视图 指的是用户页面 VM ViewModel 视图模型 视图模型是MVVM模式的核心,它是连接view和model的桥梁,MVVM实现了view和model的自动同步,当model的属性改变时,我们不用自己手动操作DOM元素,来改变view的显示,反之亦然,我们称之为数据的双向绑定。
2、v-if和v-show的区别,使用场景区别
v-if和v-show看起来似乎差不多,当条件不成立时,其所对应的标签元素都不可见,但是这两个选项是有区别的: 1、v-if在条件切换时,会对标签进行适当的创建和销毁,而v-show则仅在初始化时加载一次,因此v-if的开销相对来说会比v-show大。 2、v-if是惰性的,只有当条件为真时才会真正渲染标签;如果初始条件不为真,则v-if不会去渲染标签。v-show则无论初始条件是否成立,都会渲染标签,它仅仅做的只是简单的CSS(display)切换。 3、 v-if适用于不需要频繁切换元素显示和隐藏的情况 v-show适用于需要频繁切换元素的显示和隐藏的场景。
3、事件修饰符和按键修饰符有哪些
事件修饰符: .prevent 阻止事件默认行为 .stop 阻止事件冒泡 .capture 设置事件捕获机制 .self 只有点击元素自身才能触发事件 .once 事件只触发一次 按键修饰符: .tab .enter .esc .space .delete(捕获"删除"和"空格"键) .up .down .left .right
4、v-model修饰符有哪些
.trim 去除首尾空格 .lazy 只在输入框失去焦点或按回车键时更新内容,不是实时更新 .number 将数据转换成number类型(原本是字符串类型)
5、v-for中为什么要加key
作用: 1.key的作用主要是为了高效的更新虚拟DOM,提高渲染性能。 2.key属性可以避免数据混乱的情况出现。 原理: 1.vue实现了一套虚拟DOM,使我们可以不直接操作DOM元素只操作数据,就可以重新渲染页面,而隐藏在背后的原理是高效的Diff算法 2.当页面数据发生变化时,Diff算法只会比较同一层级的节点; 3.如果节点类型不同,直接干掉前面的节点,再创建并插入新的节点,不会再比较这个节点后面的子节点; 如果节点类型相同,则会重新设置该节点属性,从而实现节点更新 4.使用key给每个节点做一个唯一标识,Diff算法就可以正确失败此节点,"就地更新"找到正确的位置插入新的节点。
6、v-for和v-if的优先级
v-for优先级高于v-if 如果同时出现v-for和v-if,无论判断条件是否成立,都会执行一遍v-for循环,这样浪费性能,所以要尽可能的避免两者一起使用。
7、组件中的data为什么是函数,new Vue 实例里,data 可以直接是一个对象
因为组件是用来复用的,且 JS 里对象是引用关系,如果组件中 data 是一个对象,那么这样作用域没有隔离,子组件中的 data 属性值会相互影响,如果组件中 data 选项是一个函数,那么每个实例可以维护一份被返回对象的独立的拷贝,组件实例之间的 data 属性值不会互相影响;而 new Vue 的实例,是不会被复用的,因此不存在引用对象的问题。
8、computed和watch的区别是什么
计算属性computed: 1、支持缓存,只有依赖数据发生改变,才会重新进行计算 2、不支持异步,当computed内有异步操作时无效,无法监听数据的变化 3、如果computed需要对数据修改,需要写get和set两个方法,当数据变化时,调用set方法。 4、computed擅长处理的场景:一个数据受多个数据影响,例如购物车计算总价 侦听属性watch: 1、不支持缓存,数据变,直接会触发相应的操作; 2、watch支持异步;监听的函数接收两个参数,第一个参数是最新的值;第二个参数是输入之前的值; 3、immediate:组件加载立即触发回调函数执行 4、deep:true的意思就是深入监听,任何修改obj里面任何一个属性都会触发这个监听器里的 handler方法来处理逻辑 5、watch擅长处理的场景:一个数据影响多个数据,例如搜索框
9、组件化和模块化的区别
1、组件相当于库,把一些能在项目里或者不同类型项目中可复用的代码进行工具性的封装。 2、模块相应于业务逻辑模块,把同一类型项目里的功能逻辑进行进行需求性的封装。
10、怎么理解vue中的虚拟DOM
原理: 用 JavaScript 对象模拟真实 DOM 树,对真实 DOM 进行抽象; diff 算法 — 比较两棵虚拟 DOM 树的差异; pach 算法 — 将两个虚拟 DOM 对象的差异应用到真正的 DOM 树。 好处: 1、性能优化 2、无需手动操作DOM 3、可以跨平台,服务端渲染等
11、怎么理解vue的生命周期
vue的生命周期:vue实例从创建到销毁的全过程,这个过程可以分为3个阶段 第一阶段:初始化阶段 创建vue实例,准备数据,准备模板,渲染视图 第二阶段:数据更新阶段 当数据变化时,会进行新旧DOM的对比,对比出差异的部分,进行差异化更新。 第三阶段:实例销毁阶段 当vm.$destroy()被调用,vue实例就会被销毁,释放相关资源,此时再更新数据,视图不会再变化。
12、vue 钩子函数有哪些,有哪些使用的场景
1、各阶段包含钩子: beforeCreate 在data数据注入到vm实例之前,此时vm身上没有数据 created 在data数据注入到vm实例之前,此时vm身上有数据 beforeMount 生成的结构替换视图之前,此时DOM还没更新 mounted 生成的结构替换视图之前,此时DOM已经更新完成 beforeUpdate 数据变化了,dom更新之前 updated 数据变化了,dom更新之后 activated 被keep-alive缓存的组件激活时调用 deactivated 被keep-alive缓存的组件停用时调用 beforeDestroy 实例销毁,是否资源之前 destroyed 实例销毁,是否资源之后 errorCaptured 当捕获一个来自子孙组件的错误时被调用 这些钩子函数会在vue的生命周期的不同阶段,自动被vue调用 2、常用的钩子函数使用场景: beforeCreate 做loading的一些渲染 created 结束loading, 发送数据的请求,拿数据 mounted 可以对dom进行操作 updated 监视数据的更新 beforeDestroy 销毁非vue资源,防止内存泄漏,例如清除定时器 activated 当我们运用了组件缓存时,如果想每次切换都发送一次请求的话,需要把请求函数写在activated中,而写在created或mounted中其只会在首次加载该组件的时候起作用。
13、Vue 的父组件和子组件生命周期钩子函数执行顺序
1、Vue 的父组件和子组件生命周期钩子函数执行顺序可以归类为以下 4 部分: 1)加载渲染过程 父 beforeCreate -> 父 created -> 父 beforeMount -> 子 beforeCreate -> 子 created -> 子 beforeMount -> 子 mounted -> 父 mounted 2)子组件更新过程 父 beforeUpdate -> 子 beforeUpdate -> 子 updated -> 父 updated 3)父组件更新过程 父 beforeUpdate -> 父 updated 4)销毁过程 父 beforeDestroy -> 子 beforeDestroy -> 子 destroyed -> 父 destroyed
14、vue组件传值的方式
1、父传子 通过props传递 父组件: <child :list = 'list' /> 子组件: props['list'],接收数据,接受之后使用和data中定义数据使用方式一样 2、子传父 在父组件中给子组件绑定一个自定义的事件,子组件通过$emit()触发该事件并传值。 父组件: <child @receive = 'getData' /> getData(value){value就是接收的值} 子组件: this.$emit('receive',value) 3、兄弟组件传值 通过中央通信 let bus = new Vue() A组件:methods :{ sendData(){ bus.$emit('getData',value) } 发送 B组件:created(){ bus.$on(‘getData’,(value)=>{value就是接收的数据}) } 进行数据接收
15、$nextTick是什么?原理是什么
背景: 1、简单来说,Vue 在修改数据后,视图不会立刻更新,而是等同一事件循环中的所有数据变化完成之后,再统一进行视图更新。 定义: 2、在下次 DOM 更新循环结束之后执行延迟回调。在修改数据之后立即使用这个方法,获取更新后的 DOM。nextTick(),是将回调函数延迟在下一次dom更新数据后调用,简单的理解是:当数据更新了,在dom中渲染后,自动执行该函数。 原理 3、vue用异步队列的方式来控制DOM更新和nextTick回调先后执行。 简单来说,nextTick是做了promise加上setTimeout的封装,利用事件换行机制,来确保当nextTick出现时,都是在我们所有操作DOM更新之后的。 场景: 4.1 点击获取元素宽度 4.2 使用swiper插件通过 ajax 请求图片后的滑动问题 4.3 点击按钮显示原本以 v-show = false 隐藏起来的输入框,并获取焦点
16、vue是如何获取DOM
1、先给标签设置一个ref值,再通过this.$refs.domName获取,这个操作要在mounted阶段进行。 2、例如: <template> <div ref="test"></div> </template> mounted(){ const dom = this.$refs.test }
17、v-on可以监听多个方法吗
可以 例如: <input type="text" v-on="{ input:onInput,focus:onFocus }">
18、谈谈你对 keep-alive 的了解
1、keep-alive 是 Vue 内置的一个组件,可以使被包含的组件保留状态,避免重新渲染 2、一般结合路由和动态组件一起使用,用于缓存组件 3、对应两个钩子函数 activated 和 deactivated ,当组件被激活时,触发钩子函数 activated,当组件被移除时,触发钩子函数 deactivated 4、提供 include 和 exclude 属性,两者都支持字符串或正则表达式, include 表示只有名称匹配的组件会被缓存,exclude 表示任何名称匹配的组件都不会被缓存 ,其中 exclude 的优先级比 include 高; 例如: <keep-alive include="a"> <component> <!-- name 为 a 的组件将被缓存! --> </component> </keep-alive> <keep-alive exclude="a"> <component> <!-- 除了 name 为 a 的组件都将被缓存! --> </component> </keep-alive>
19、谈谈你对slot的了解
1、什么是插槽 1.1 插槽(Slot)是Vue提出来的一个概念,正如名字一样,插槽用于决定将所携带的内容,插入到指定的某个位置,从而使模板分块,具有模块化的特质和更大的重用性。 1.2 插槽显不显示、怎样显示是由父组件来控制的,而插槽在哪里显示就由子组件来进行控制 2、插槽使用 2.1 默认插槽 在子组件中写入slot,slot所在的位置就是父组件要显示的内容 2.2 具名插槽 在子组件中定义了三个slot标签,其中有两个分别添加了name属性header和footer 在父组件中使用template并写入对应的slot名字来指定该内容在子组件中现实的位置 2.3 作用域插槽 在子组件的slot标签上绑定需要的值<slot :data="user"></slot> 在父组件上使用slot-scope=“user”来接收子组件传过来的值
20、vue中动态组件如何使用
1、在某个中使用 is 特性来切换不同的组件: <component :is="TabComponent"></component> TabComponent:已注册组件的名字
21、v-model的原理是什么
1、v-model主要提供了两个功能,view层输入值影响data的属性值,属性值发生改变会更新层的数值变化. 2、v-model指令的实现: 3.1 v-bind:绑定响应式数据 3.2 触发input事件并传递数据 (核心和重点) 3、其底层原理就是(双向数据绑定原理): 3.1 一方面modal层通过defineProperty来劫持每个属性,一旦监听到变化通过相关的页面元素更新。 3.2 另一方面通过编译模板文件,为控件的v-model绑定input事件,从而页面输入能实时更新相关data属性值。
22、vue响应式vue的原理
1、原理: Vue 的响应式原理是核心是通过 ES5 的 Object.defindeProperty 进行数据劫持,然后利用 get 和 set 方法进行获取和设置,data 中声明的属性都被添加到了get和set中,当读取 data 中的数据时自动调用 get 方法,当修改 data 中的数据时,自动调用 set 方法,检测到数据的变化,会通知观察者 Wacher,观察者 Wacher自动触发重新render 当前组件(子组件不会重新渲染),生成新的虚拟 DOM 树,Vue 框架会遍历并对比新虚拟 DOM 树和旧虚拟 DOM 树中每个节点的差别,并记录下来,最后,加载操作,将所有记录的不同点,局部修改到真实 DOM 树上。 2、底层代码实现: let data = { name: "lis", age: 20, sex: "男" } // vue2.0实现 使用Object.defineProperty进行数据劫持 for(let key in data){ let temp = data[key] Object.defineProperty(data, data[key], { get(){ return temp }, set(value){ temp = value } }) } // vue3.0实现 使用Proxy 进行数据的代理 let newData = new Proxy(data, { get(target, key){ return target[key] }, set(target, key, value){ target[key] = value } })
23、vue2.0和vue3.0响应式的区别
1、Object.defineProperty 1) 用于监听对象的数据变化 2) 无法监听数组变化(下标,长度) 3) 只能劫持对象的自身属性,动态添加的劫持不到 2、Proxy 1) proxy返回的是一个新对象, 可以通过操作返回的新的对象达到目的 2)可以监听到数组变化,也可以监听到动态添加的数据
24、router和route的区别
1、$router对象 1)$router对象是全局路由的实例,是router构造方法的实例 2)$router对象上的方法有:push()、go()、replace() 2、$route对象 1)$route对象表示当前的路由信息,包含了当前 URL 解析得到的信息。包含当前的路径,参数,query对象等 2)$route对象上的属性有:path、params、query、hash等等
25、路由传参的方式和区别
答: 1、方式:params 和 query 2、区别:1)params用的是name,传递的参数在地址栏不会显示,类似于post 2)query用的是path,传递的参数会在地址栏显示出来,类似于get 3、举例说明: 1)params 传参 传: this.$router.push({ name: 'particulars', params: { id: id } }) 接:this.$route.params.id 2)query传参 传:this.$router.push({ path: '/particulars', query: { id: id } }) 接:this.$route.query.id
闭包就是 函数里面还有个函数 里面函数访问外面函数的变量 不再使用 浏览器不会清理这个变量 导致内存泄露