vue的优势有哪些?
1)轻量级框架:只关注视图层,是一个构建数据的视图集合。
2)双向数据绑定,数据操作方面更加简单
3)组件化:实现html封装和重用
4)视图、数据、结构分离:使数据更改更加简单,不需修改逻辑代码,只需操作数据
5)虚拟DOM:DOM的操作比较耗性能,不使用原生的DOM操作节点
ps:vue不利于SEO
Vue中watch和computed的区别
1、computed是计算属性;watch是监听,监听data中的数据变化。
2、computed支持缓存,当其依赖的属性的值发生变化时,计算属性会重新计算,反之,则使用缓存中的属性值;watch不支持缓存,当对应属性发生变化的时候,响应执行。
3、computed不支持异步,有异步操作时无法监听数据变化;watch支持异步操作。
4、computed第一次加载时就监听;watch默认第一次加载时不监听。immediate 组件创建时刻执行与否
immediate: true,第一次加载时监听(默认为false)
deep 深度监听 不推荐使用(非常的消耗性能)
监听的属性是对象的话 不开启deep 对象子属性变化不会触发watch
开启了deep 对象内部所有子属性变化 都会触发watch
5、computed中的函数必须调用return;watch不是。
6、使用场景:
computed:一个属性受到多个属性影响,如:购物车商品结算。
watch:一个数据影响多条数据,如:搜索数据。
数据变化响应,执行异步操作,或高性能消耗的操作,watch为最佳选择。
绑定 class 的数组用法
- 对象方法 v-bind:class="{' orange': isRipe,'green': isNotRipe}"
- 数组方法 V-bind:class="[class1,class2]"
- 行内 v-bind:style="{color: color, fontSize: fontSize+'px'}"
开发中常用的指令有哪些
v-show v-if v-html v-text v-model v-on v-clock v-bind
修饰符有哪些
事件修饰符
- .stop 阻止事件继续传播
- .prevent 阻止标签默认行为
- .capture 使用事件捕获模式,即元素自身触发的事件先在此处处理,然后才交由内部元素进行处理
- .self 只当在 event.target 是当前元素自身时触发处理函数
- .once 事件将只会触发一次
- .passive 告诉浏览器你不想阻止事件的默认行为
v-model 的修饰符
- .lazy 通过这个修饰符,转变为在 change 事件再同步
- .number 自动将用户的输入值转化为数值类型
- .trim 自动过滤用户输入的首尾空格
vue的插槽(slot)主要分三种:
默认插槽,具名插槽,作用域插槽
vue中的插槽,指的是子组件中提供给父组件使用的一个占位符;
用标签表示,父组件可以在这个占位符中填充任何模板代码,比如HTML、组件等,填充的内容会替换掉子组件的标签(替换占位符)。
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 =Sevent.target.value">
如果在自定义组件中,v-model 默认会利用名为 value 的 prop 和名为 input的事件,如下所示:
父组件:
<ModelChild v-model="message"></ModelChild>子组件:
<div>{{value}}</div>props:value:String
},
methods:{test1(){this.$emit('input','小红')},
},
Vue的生命周期
Vue实例创建到销毁的过程称为生命周期。从开始创建、初始化数据、编译模板、挂载DOM->渲染->更新->渲染、卸载等一系列过程称为vue的生命周期。
相关知识点:
1)vue生命周期总共8个阶段:创建前后、载入前后、更新前后、销毁前后
2)第一次触发会触发几个钩子:beforeCreate created beforeMount mounted
3)DOM渲染在哪个生命周期已经完成:mounted
4)vue中父子组件钩子的执行顺序:
父beforeCreate->父created->父beforeMount->子beforeCreate->子created->子beforeMount->子mounted->父mounted
更新:父beforeUpdate->子beforeUpdate->子updated->父updated
销毁:父beforeDestory->子beforeDestory->子destoryed->父destoryed
vue生命周期的作用
在控制整个vue实例过程中形成良好的逻辑。(生命周期中的多个事件钩子)
vue组件间的通信
1)vuex
2)eventBus
3)props/emit
4)$parent/$children
5)$attrs/$listeners
双向绑定数据的原理
Vue的数据双向绑定是通过数据劫持结合发布者-订阅者模式的方式实现。通过Object.defineProperty()来劫持各个属性的getter/setter。修改触发了方法set方法赋值,获取触发了get方法取值,在数据发生变动时发送消息给订阅者,触发相应的回调并通过数据劫持发布消息
响应式是指组件data数据一旦发生变化,立即触发视图的更新。他是实现数据驱动视图的第一步。
vue响应式一个核心api是Object.defineProperty(). 利用Object.defineProperty重写get和set,将对象属性的赋值和获取变成函数,我们可以实现一个简单的双向绑定。
解释单向数据流和双向数据绑定
单向数据流: 顾名思义,数据流是单向的。数据流动方向可以跟踪,流动单一,追查问题的时候可以更快捷。缺点就是写起来不太方便。要使 UI 发生变更就必须创建各种 action
来维护对应的 state
。
双向数据绑定:数据之间是相通的,将数据变更的操作隐藏在框架内部。优点是在表单交互较多的场景下,会简化大量与业务无关的代码。缺点就是无法追踪局部状态的变化,增加了出错时 debug 的难度。
vue组件中data为什么必须是函数
因为JS本身特性带来的,如果data是一个对象,那么由于对象本身属于引用类型,当我们改变其中一个属性时,会影响到vue实例的数据。如果data作为一个函数返回一个对象,那么每个实例的data都是独立的,不会互相影响。
真实DOM和虚拟DOM
假如一次操作中有10次更新DOM的动作,当你用传统的源生api或jQuery去操作DOM时,浏览器会从构建DOM树开始从头到尾执行一遍流程;
但是虚拟DOM不会立即操作DOM,而是将这10次更新的diff内容保存到本地的一个js对象中,最终将这个js对象一次性attach到DOM树上,通知浏览器去执行绘制工作,再进行后续操作,避免大量无谓的计算量。
Vue中key的作用
vue 中 key 值的作用可以分为两种情况来考虑:
- 第一种情况是 v-if 中使用 key。由于 Vue 会尽可能高效地渲染元素,通常会复用已有元素而不是从头开始渲染。因此当使用 v-if 来实现元素切换的时候,如果切换前后含有相同类型的元素,那么这个元素就会被复用。如果是相同的 input 元素,那么切换前后用户的输入不会被清除掉,这样是不符合需求的。因此可以通过使用 key 来唯一的标识一个元素,这个情况下,使用 key 的元素不会被复用。这个时候 key 的作用是用来标识一个独立的元素。
- 第二种情况是 v-for 中使用 key。用 v-for 更新已渲染过的元素列表时,它默认使用“就地复用”的策略。如果数据项的顺序发生了改变,Vue 不会移动 DOM 元素来匹配数据项的顺序,而是简单复用此处的每个元素。因此通过为每个列表项提供一个 key 值,来以便 Vue 跟踪元素的身份,从而高效的实现复用。这个时候 key 的作用是为了高效的更新渲染虚拟 DOM。
key 是为 Vue 中 vnode 的唯一标记,通过这个 key,diff 操作可以更准确、更快速
- 更准确:因为带 key 就不是就地复用了,在 sameNode 函数a.key === b.key对比中可以避免就地复用的情况。所以会更加准确。
- 更快速:利用 key 的唯一性生成 map 对象来获取对应节点,比遍历方式更快
v-for 为什么要加 key
如果不使用 key,Vue 会使用一种最大限度减少动态元素并且尽可能的尝试就地修改/复用相同类型元素的算法。key 是为 Vue 中 vnode 的唯一标记,通过这个 key,我们的 diff 操作可以更准确、更快速
更准确:因为带 key 就不是就地复用了,在 sameNode 函数 a.key === b.key 对比中可以避免就地复用的情况。所以会更加准确。
更快速:利用 key 的唯一性生成 map 对象来获取对应节点,比遍历方式更快
hash和history
1. vue-router(前端路由)有两种模式,hash模式和history模式
1).hash 就是指 url 后面的 # 号以及后面的字符,history没有带#,外观上比hash 模式好看些
2).原理的区别(原理)
3). hash 能兼容到IE8, history 只能兼容到 IE10;
4).由于 hash 值变化不会导致浏览器向服务器发出请求,而且 hash 改变会触发 hashchange 事件(hashchange只能改变 # 后面的url片段);虽然hash路径出现在URL中,但是不会出现在HTTP请求中,对后端完全没有影响,因此改变hash值不会重新加载页面,基本都是使用 hash 来实现前端路由的。
2.原理:
1).hash通过监听浏览器的onhashchange()事件变化,查找对应的路由规则
2).history原理: 利用H5的 history中新增的两个API pushState() 和 replaceState() 和一个事件onpopstate监听URL变化
history模式URL就要和后端进行一致,所以要改为history也需要后端的配合,否则会报错。
所以hash模式在每次刷新页面时是直接更改“#”后的东西,history每次刷新会重新像后端请求整个网址,也就是重新请求服务器。如果后端没有及时响应,就会报错404!。history的好处是可以进行修改历史记录,并且不会立刻像后端发起请求。不过如果对于项目没有硬性标准要求,我们可以直接使用hash模式开发。
(1)hash 模式的实现原理
早期的前端路由的实现就是基于 location.hash 来实现的。其实现原理很简单,location.hash 的值就是 URL 中 # 后面的内容。比如下面这个网站,它的 location.hash 的值为 ‘#search’:
https://www.word.com#search
hash 路由模式的实现主要是基于下面几个特性:
- URL 中 hash 值只是客户端的一种状态,也就是说当向服务器端发出请求时,hash 部分不会被发送;
- hash 值的改变,都会在浏览器的访问历史中增加一个记录。因此我们能通过浏览器的回退、前进按钮控制hash 的切换;
- 可以通过 a 标签,并设置 href 属性,当用户点击这个标签后,URL 的 hash 值会发生改变;或者使用 JavaScript 来对 loaction.hash 进行赋值,改变 URL 的 hash 值;
- 我们可以使用 hashchange 事件来监听 hash 值的变化,从而对页面进行跳转(渲染)。
(2)history 模式的实现原理HTML5 提供了 History API 来实现 URL 的变化。其中做最主要的 API 有以下两个:history.pushState() 和 history.repalceState()。这两个 API 可以在不进行刷新的情况下,操作浏览器的历史纪录。 **唯一不同的是,前者是新增一个历史记录,后者是直接替换当前的历史记录,如下所示:** window.history.pushState(null, null, path); window.history.replaceState(null, null, path);
- history 路由模式的实现主要基于存在下面几个特性:
- pushState 和 repalceState 两个 API 来操作实现 URL 的变化 ;
- 我们可以使用 popstate 事件来监听 url 的变化,从而对页面进行跳转(渲染);
- history.pushState() 或 history.replaceState() 不会触发 popstate 事件,这时我们需要手动触发页面跳转(渲染)。
vue初始化页面闪动问题
使用vue开发时,在vue初始化之前,由于div是不归vue管的,所以我们写的代码在还没有解析的情况下会容易出现花屏现象,看到类似于{{message}}的字样,虽然一般情况下这个时间很短暂,但是还是有必要让解决这个问题的。
首先:在css里加上以下代码:v-cloak] { display: none;}
如果没有彻底解决问题,则在根元素加上style="display: none;" :style="{display: 'block'}
Vue怎么动态增加对象属性
1.this.$set(this.obj,key,value)
2.this.obj=Object.assign({},this.obj,{a:1,b:2});
路由守卫的生命周期
1.全局路由守卫的生命周期:
(1) router.beforeEach((to,from,next)=>{ })
生效时机:导航触发时
(2) router.beforeResolve((to,from,next)=>{ })
生效时机:导航被确认之前,同时在所有组件内守卫和异步路由组件被解析之后
(3)router.afterEach((to,from)=>{ })
2.局部路由守卫的生命周期:
(1)beforRouteEnter(to,from,next){ }
注意:在渲染改组件对应的路由被加载进界面前调用,不能使用'this'获取组件实例,因为守卫执行前,组件实例还被没被创建
(2)beforeRouteUpdate(to,from,next){ }
注意:当前路由发生改变时调用,可以使用'this'访问组件实例
(3)beforeRouterLeave(to,from,next){ }
注意:导航离开该组件对应的路由时调用,可以使用'this'访问组件实例
route和router 的区别
route 是用来获取路由信息的,router是用来操作路由的。
Vue-Router
vue-router 是 Vue.js 官方的路由管理器,它和 Vue.js 的核心深度集成,让构建单页面应用变得易如反掌。包含的功能有:
- 嵌套的路由
- 模块化的、基于组件的路由配置
- 路由参数、查询、通配符
- 基于 Vue.js 过度系统的视图过渡效果
- 细颗粒度的导航控制
- 带有自动激活的 CSS class 的连接
- history模式或 hash 模式,在 IE9 中自动降级
- 自定义的滚动条行为
vue-router 组件:
- < router-link to=""> 路由的路径
- < router-link :to="{name:’‘l路由名’}"> 命名路由
- < router-view> 路由的显示
vue-router 有哪几种导航钩子
1.全局导航钩子
1)前置钩子:
router.beforeEach((to, from, next) => { })
2)后置钩子
router.afterEach((to,from) => { })
2.单独路由独享钩子
{
path: '/home',
name: 'home',
component: Home,
beforeEnter(to, from, next) {
if (window.localStorage.getItem("id")) {
next()
} else {
next({ name: "login" })
}
}
}
3.组件内的钩子
beforeRouteEnter(to, from, next) {
// do someting
// 在渲染该组件的对应路由被 confirm 前调用
},
beforeRouteUpdate(to, from, next) {
// do someting
// 在当前路由改变,但是依然渲染该组件是调用
},
beforeRouteLeave(to, from ,next) {
// do someting
// 导航离开该组件的对应路由时被调用
}
全局解析守卫
router.beforeResolve 注册一个全局守卫,和 router.beforeEach 类似
Vite打包优势
1)快速冷启动
2)打包编译速度
3)热模块更新
说说VUEX
- state:放状态的地方,vuex的基本数据,用来存储变量
- Mutation:提交更新数据的方法,同步的
- getter:从基本数据state派生的数据,相当于state的计算属性
- action:和Mutation功能大致相同,不同在于,action提交的是mutation,而不是直接更改状态。action可以包含任意异步操作。
- modules:模块化VUEX,可以让每个模块都有自己的state mutation action getter
Vue2和Vue3的区别
1. 响应式系统的重构,使用proxy替换Object.defineProperty属性,优势:
- Proxy可直接监听 对象`添加/删除`属性;
- Proxy直接监听 数组的变化
- Proxy监听的目标是对象本身,不需要像Object.defineProperty那样遍历每个属性,有一定的性能提升
2. 新增`组合式API`(Composition API),更好的逻辑重用和代码组织:
- setup配置
- ref与reactive
- watch与watchEffect
- provide与inject
3. 重构虚拟 DOM, diff算法
4. 生命周期更名
- beforeDestroy改名为 beforeUnmount
- destroyed改名为 unmounted
// Vue3.0也提供了 Composition API 形式的生命周期钩子,与Vue2.x中钩子对应关系如下:
vue3:onBeforeMounted=>onMounted=>onBeforeUpdate=>onUpdated=>onBeforeUnmount
beforeCreate ===> setup()
created ===> setup()
beforeMount ===> onBeforeMount
mounted ===> onMounted
beforeUpdate ===> onBeforeUpdate
updated ===> onUpdated
beforeUnmount===> onBeforeUnmount
unmounted ===> onUnmounted
4. 新的内置组件:
- Fragment
- Teleport
- Suspense
5. 移除的部分:
- 移除v-on.keyCode修饰符,同时也不再支持config.keyCodes
- 移除v-on.native修饰符,
- 移除过滤器(filter)
- `不`再建议使用mixins, 组合式函数本身就是更好的mixin代替品
6.数据和方法的定义
vue2: data() { return {}; }, methods:{ }
vue3:据和⽅法都定义在setup中,并统⼀进⾏
return{}
watch和watcheffect
计算属性 computed 和事件 methods 有什么区别
我们可以将同一函数定义为一个 method
或者一个计算属性。对于最终的结果,两种方式是相同的。
不同点:
-
computed
:计算属性是基于它们的依赖进行缓存的,只有在它的相关依赖发生改变时才会重新求值。 -
method
:只要发生重新渲染,method
调用总会执行该函数。
管理多个页面数据模块解耦合(vuex)
Vue 的核心是什么
数据驱动、组件系统。
Vue中$nextTick()的作用和原理
Vue在更新Dom时是异步执行的,在修改数据后,视图不会立即更新,而是在等同一时间就循环中的所有变化完成后,再统一对视图进行更新。所以我们在修改完数据,立即在方法中获取DOM,获取的仍是未修改的DOM。
$nextTick是下次DOM更新循环结束之后的延迟回调。DOM更新后再自动执行
里面的函数。
$nextTick作用:该方法中的代码会在渲染完成后执行,解决了异步渲染获取不到最新DOM的问题
应用场景:在钩子函数created()里面想要获取操作DOM,把操作DOM的方法放于$nextTick里面
MVC解释
MVC全名是Model View Controller,是模型(model)-视图(view)-控制器(controller)的缩写,一种软件设计典范,用一种业务逻辑、数据、界面显示分离的方法组织代码,将业务逻辑聚集到一个部件里面,在改进和个性化定制界面及用户交互的同时,不需要重新编写业务逻辑。MVC被独特的发展起来用于映射传统的输入、处理和输出功能在一个逻辑的图形化用户界面的结构中。
几乎所有的App都只干这么一件事:将数据展示给用户看,并处理用户对界面的操作。
MVC的思想:一句话描述就是Controller负责将Model的数据用View显示出来,换句话说就是在Controller里面把Model的数据赋值给View。
MVVM
MVVM:Model、View、ViewModel。
你会下意识地把它和MVC来对比,你会发现,MVVM多了一个ViewModel而少了Controller。
首先说一下多出来的ViewModel(VM,不是显存)。
VM的意义,和Model一样,在于数据。
Model负责对数据进行取和存,然而我们对数据的操作除了取和存以外,还有一个非常重要的操作:解析。
MVVM模式
MVVM核心思想,是关注model的变化,让MVVM框架利用自己的机制自动更新DOM,也就是所谓的数据-视图分离,数据不会影响视图。(视图{页面}-模型{数据}-模型视图{桥梁视图与数据之间的转换处理})
1)MVVM 实现了数据与页面的双向绑定
2)MVVM 实现了页面业务逻辑和渲染之间的解耦,也实现了数据与视图的解耦,并且可以组件化开发。
3)VUE是如何体现MVVM思想的:胡子语法,实现了数据与视图的绑定;v-on 事件绑定,通过事件操作数据时,v-model 会发生相应的变化。
MVC解释
MVC全名是Model View Controller,是模型(model)-视图(view)-控制器(controller)的缩写,一种软件设计典范,用一种业务逻辑、数据、界面显示分离的方法组织代码,将业务逻辑聚集到一个部件里面,在改进和个性化定制界面及用户交互的同时,不需要重新编写业务逻辑。MVC被独特的发展起来用于映射传统的输入、处理和输出功能在一个逻辑的图形化用户界面的结构中。
几乎所有的App都只干这么一件事:将数据展示给用户看,并处理用户对界面的操作。
MVC的思想:一句话描述就是Controller负责将Model的数据用View显示出来,换句话说就是在Controller里面把Model的数据赋值给View。
MVVM
什么是MVVM
MVVM:Model、View、ViewModel。
你会下意识地把它和MVC来对比,你会发现,MVVM多了一个ViewModel而少了Controller。
首先说一下多出来的ViewModel(VM,不是显存)。
VM的意义,和Model一样,在于数据。
Model负责对数据进行取和存,然而我们对数据的操作除了取和存以外,还有一个非常重要的操作:解析。