个人主页:不爱吃糖的程序媛
♂️ 作者简介:前端领域新星创作者、CSDN内容合伙人,专注于前端各领域技术,成长的路上共同学习共同进步,一起加油呀!
✨系列专栏:前端面试宝典、JavaScript进阶、vue实战
资料领取:前端进阶资料以及文中源码可以在公众号“不爱吃糖的程序媛”领取
页面初次渲染的时候:
父beforeCreate-> 父created -> 父beforeMount
子beforeCreate-> 子created ->子beforeMount-> 子mounted
父mounted
页面更新的时候:
子beforeUpdate > 子updated
父beforeUpdate > 父updated
父beforeDestory
子beforeDestory->子destoryed
父destoryed
不可以,created没有实例可以操作,可以查看但是不能操作。
推荐在 created 钩子函数中调用异步请求,因为在 created 钩子函数中调用异步请求有以下优点:能更快获取到服务端数据,减少页面loading 时间;
在created阶段,实例已经被初始化,但是还没有挂载至el上,所以我们无法获取到对应的节点,但是此时我们是可以获取到vue中data与methods中的数据的;
在mounted阶段,vue的template成功挂载在$el中,此时一个完整的页面已经能够显示在浏览器中,所以在这个阶段,可以调用节点了;
第一步是将 模板字符串 转换成 element ASTs(解析器)
第二步是对 AST 进行静态节点标记,主要用来做虚拟DOM的渲染优化(优化器)
第三步是 使用 element ASTs 生成 render 函数代码字符串(代码生成器)
模板字符串>>------转换为element ASTs>>对AST进行静态节点标记(虚拟dom的渲染优化)>>-----使用element AST生成render函数代码字符串
第一步的具体过程:vue怎么将 template 转化成 render 函数:将模板字符串会扔到 while中去循环,然后一段一段的截取,把截取到的进行解析,直到最后截没了,这时就解析成了element AST。
V-bind:value v-on:input
我们就以v-model为例吧,当我们使用v-model的时候,其实它是一个语法糖,它实现了绑定value,监听input事件。所以它把双向绑定拆成两个单向绑定,第一种是实现value的绑定,实现了当你去改变data的时候,我的ui就直接改变的单向绑定;另一方面我们监听了input,触发了input事件,我们就去更新data,这样一个单向绑定。两个单向绑定加起来就是双向绑定。
前者是通过object.defineProperty API给data的每一个属性递归的创建getter和setter,既然我把getter和setter相互做了一个监听,那么data一变就会安排改变ui。
后者是通过template compiler给dom添加事件监听,dom input的值变了就会去修改data。
1、vue是单页面应用,使页面局部刷新,不用每次跳转页面都要请求所有数据和dom,这样大大加快了访问速度和提升用户体验。
2、双向数据绑定:保留了 angular 的特点,在数据操作方面更为简单;
3、mvvm的模式,视图、数据和结构的分离,使数据的更改更为简单,不需要进行逻辑代码的修改,只需要操作数据就能完成相关操作;让项目更加好维护。
4、轻量级框架:只关注视图层,是一个构建数据的视图集合,大小只有几十 kb ;
5、组件化:保留了 react 的优点,实现了 html 的封装和重用,在构建单页面应用方面有着独特的优势;
6、虚拟DOM:dom 操作是非常耗费性能的, 不再使用原生的 dom 操作节点,极大解放 dom 操作,但具体操作的还是 dom 不过是换了另一种方式;
7、简单易学:国人开发,中文文档,不存在语言障碍 ,易于理解和学习;
8、运行速度更快:相比较于 react 而言,同样是操作虚拟 dom ,就性能而言, vue 存在很大的优势。
1、vue直接的框架不可以做seo,如果要做的话需要预渲染或服务器端渲染。
2、用js去渲染数据,第一次会造成重绘或者回流,性能有一定的影响。
3、VUE不支持IE8
4、生态环境差不如angular和react
5、可扩展性稍差
Vue与react的区别:
共同点
数据驱动视图
组件化
都使用 Virtual DOM
不同点
1.监听数据变化的实现原理不同
Vue通过getter/setter方法以及一些函数的劫持能精确知道数据的变化。
React默认是通过比较引用方式diff算法进行的,若不优化,会导致大量不必要的VDom的重新渲染。
2.数据流不同
Vue实现双向绑定:props可以双响绑定,组件与Dom之间可以通过v-model绑定。
React不支持双向绑定:提倡单向数据流,称之为onChange/setState模式。
3.组件通信的区别
Vue中有三种方式可以实现组件通信:
a. 父组件通过props向子组件传递数据或者回调,虽然可以传递回调,但是一般只传递数据;
b. 子组件通过事件向父组件发送消息;
c. 通过Vue2.2中新增的provide/inject来实现父组件向子组件注入数据,可以跨越多个层级。
React中有三种方式实现组件通信:
a. 父组件通过props向子组件传递数据或者回调;
b. 可以通过context进行跨层级的通信;
c. React本身不支持自定义事件,而Vue中子组件向父组件传递消息有两种方式:事件和回调函数。
4.模板渲染方式不同
在表层上,模板的语法不同。React是通过jsx来渲染模板,Vue是通过一种拓展的html语法来进行渲染,但其实这只是表面现象,毕竟React并不必依赖jsx.
在深层上,模板的原理不同。本质的区别在于:React是在组件js代码中,通过原生js实现模板汇总的常见语法,比如插值、条件、循环等,都是通过js语法实现,更加纯粹、原生;而Vue是在和组件js代码分离的单独模板中,通过指令来实现的,比如条件语句v-if。
5.模板渲染过程不同
Vue可以更快的计算出Virtual Dom的差异,这是由于它在渲染过程中,会跟踪每个组件的依赖关系,不需要更新渲染整个组件树。
React在应用的状态被改变时,全部子组件都会重新渲染。通过shouldComponentUpdate这个生命周期函数可以进行控制,但Vue将次视为默认的优化。
如果应用中交互复杂,需要处理大量的UI变化,那么使用Virtual Dom是一个好主意,如果更新不频繁,可以直接操控DOM。
6.框架本质不同
Vue本职是MVVM框架,由MVC发展而来。
React是前端组件框架,由组件演化而来。
对于Computed:
• 它支持缓存,只有依赖的数据发生了变化,才会重新计算
• 不支持异步监听,当Computed中有异步操作时,无法监听数据的变化
• computed的值会默认走缓存,计算属性是基于它们的响应式依赖进行缓存的,也就是基于data声明过,或者父组件传递过来的props中的数据进行计算的。
• 如果一个属性是由其他属性计算而来的,这个属性依赖其他的属性,一般会使用computed
• 如果computed属性的属性值是函数,那么默认使用get方法,函数的返回值就是属性的属性值;在computed中,属性有一个get方法和一个set方法,当数据发生变化时,会调用set方法。
对于Watch:
• 它不支持缓存,数据变化时,它就会触发相应的操作
• 支持异步监听
• 监听的函数接收两个参数,第一个参数是最新的值,第二个是变化之前的值
• 当一个属性发生变化时,就需要执行相应的操作
• 监听数据必须是data中声明的或者父组件传递过来的props中的数据,当发生变化时,会触发其他操作,函数有两个的参数:
o immediate:组件加载立即触发回调函数
o deep:深度监听,发现数据内部的变化,在复杂数据类型中使用,例如数组中的对象发生变化。需要注意的是,deep无法监听到数组和对象内部的变化。
总结:
1.computed 计算属性 : 依赖其它属性值,支持缓存,不支持异步监听。
2.watch 侦听器 : 更多的是观察的作用,不支持缓存性,支持异步监听。
运用场景:
• 当需要进行数值计算,并且依赖于其它数据时,应该使用 computed,因为可以利用 computed 的缓存特性,避免每次获取值时都要重新计算。
使用场景:当一个值受多个属性影响的时候------------购物车商品结算
• 当想要执行异步或开销较大的操作时以响应不断的变化时,应该使用 watch,使用 watch 选项允许执行异步操作 ( 访问一个 API ),限制执行该操作的频率,并在得到最终结果前,设置中间状态。这些都是计算属性无法做到的。
使用场景:当一条数据的更改影响到多条数据的时候---------搜索框
1.原理
v-show指令:元素始终被渲染到HTML,它只是简单的伪元素设置css的style属性,当不满足条件的元素被设置style=“display:none”的样,
是通过修改元素的的CSS属性(display)来决定实现显示还是隐藏
v-if指令:满足条件是会渲染到html中,不满足条件时是不会渲染到html中的,是通过操纵dom元素来进行切换显示。
2.应用场景
v-if需要操作dom元素,有更高的切换消耗,
v-show只是修改元素的的CSS属性,有更高的初始渲染消耗,如果需要非常频繁的切换,建议使用v-show较好,如果在运行时条件很少改变,则使用v-if较好。
1.虚拟DOM中key的作用:
key是虚拟DOM对象的标识,在更新显示时key起着极其重要的作用。
2.使用v-for更新已渲染的元素列表时,默认用就地复用策略;
(就地复用策略:如果数据项的顺序被改变,Vue 将不会移动 DOM 元素来匹配数据项的顺序,而是就地更新每个元素,并且确保它们在每个索引位置正确渲染)
列表数据修改的时候,他会根据key值去判断某个值是否修改,如果修改,则重新渲染这一项,否则复用之前的元素;
由于v-for的优先级比v-if高,所以导致每循环一次就会去v-if一次,而v-if是通过创建和销毁dom元素来控制元素的显示与隐藏,所以就会不停的去创建和销毁元素,造成页面卡顿,性能下降。
解决办法:
在v-for的外层或内层包裹一个元素来使用v-if
用computed处理
概念Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式+库。
解决的问题:(场景)
多个视图依赖同一个状态,
来自不同视图的行为需要变更同一状态,
适用于中大型的单页面应用。
为什么要使用Vuex?
举例子:比如一个公共组件,A要用它,B要用它,但是每个页面的轮播时间都不一样,又不能去改这个公共组件。
当我们使用 Vue.js 来开发一个单页应用时,经常会遇到一些组件间共享的数据或状态,或是需要通过 props 深层传递的一些数据。在应用规模较小的时候,我们会使用 props、事件等常用的父子组件的组件间通信方法,或者是通过事件总线来进行任意两个组件的通信。但是当应用逐渐复杂后,问题就开始出现了,这样的通信方式会导致数据流异常地混乱。
VueX的工作原理(工作流程)
1vue组件数据更新–> 通过dispatch方法 通知Actions
2Actions 通过commit 方法通知给 Mutations 在这一过程中 可以处理异步任务 ,例如发送请求,获取api数据等等,但是Mutations 不可以处理异步任务。
3真正操作的store数据的也就是Mutations 我们的vue-devtools工具 检测到的也是这一状态
4store中的数据改变 触发响应式 然后重新更新视图
vuex有哪些属性?(重点)
Store:是一个大容器,包含以下所有的内容;
state:用来读取状态,存放公共数据的地方;(附带mapState辅助函数)
getter:用来读取派生状态,获取根据业务场景处理返回的数据;(附带mapGetters辅助函数)
mutations:用于同步提交状态变更,唯一修改state的方法;(附带mapMutations辅助函数)
action:用于处理异步变更状态,通过分发操作触发mutation,不是直接变更状态;
module:给store划分模块,减少代码臃肿,方便维护代码;
使用vuex的优势是什么?
其实vuex中的所有功能都能够通过其他的方式进行实现,只不过vuex对这些方法进行了整合处理,使用起来更加便捷,同时也便于维护。
Vuex中状态储存在哪里,怎么改变它?
存储在state中,改变Vuex中的状态的唯一途径就是显式地提交 (commit) mutation。
怎么在组件中批量使用Vuex的state状态?
使用mapState辅助函数, 利用对象展开运算符将state混入computed对象中
import {mapState} from 'vuex'
export default{
computed:{
...mapState(['price','number'])
}
}
路由守卫是什么?
作用:对路由进行权限控制。(来判断用户是否登录,该页面用户是否有访问该页面权限)
路由守卫就是:
比如说,当点击商城的购物车的时候,需要判断一下是否登录,如果没有登录,就跳转到登录页面,如果登陆了,就跳转到购物车页面,相当于有一个守卫在安检。
路由守卫有三种:(全局、组件、独享)
1:全局路由守卫: 全局前置守卫、后置守卫
router.beforeEach((to,from,next)=>{})
router.afterEach((to, from) => {})
2:组件路由守卫:
beforeRouteEnter:(to,from,next)=>{}——到达
beforeRouteUpdate:(to,from,next)=>{}——路由更新之前(组件没有变化但是路由变了–动态路由)调用
beforeRouteLeave:(to,from,next)=>{}——离开
点击其他组件时,判断是否确认离开。确认执行next();取消执行next(false),留在当前页面。
2:独享路由守卫: (只能针对一个页面使用)
router.beforeEnter:(to,from,next)=>{}
每个守卫方法接收三个参数:
①to: Route: 即将要进入的目标路由对象。
②from: Route: 从哪个路由离开。
③next: Function: 决定是否展示你要看到的路由页面。
• next()用法一: next()直接通过
• next()用法二:next(“/login”):强行跳转到指定页面
• next()用法三: next(false):不允许跳转
v-html //html
v-text //元素里要显示的内容
v-bind:data //绑定动态数据 :data
v-on:click //绑定事件 @click
v-for
v-if //条件渲染指令
v-model //双向绑定,用于表单
作用:缓存组件,提升性能,避免重复加载一些不需要经常变动且内容较多的组件。
的使用方法:使用
标签对需要缓存的组件进行包裹,默认情况下被
标签包裹的组件都会进行缓存,区分被包裹的组件是否缓存有两种方法,第一种是给keepalive 添加属性,组件名称指的是具体组件添加的name,不是路由里面的name。include 包含的组件(可以为字符串,数组,以及正则表达式,只有匹配的组件会被缓存)。exclude 排除的组件(以为字符串,数组,以及正则表达式,任何匹配的组件都不会被缓存)。第二种也是最常用的一种是,和路由配合使用:在路由中添加meta属性。 使用keepalive导致组件不重新加载,也就不会重新执行生命周期的函数,如果要解决这个问题,就需要两个属性进入时触发:activated 退出时触发:deactivated 加分回答
适用的场景:首页展示固定数据的组件,比如banner九宫格
布尔,string,number,null,undefined
array,元组,枚举,any,void,never,object,断言
Any unknown二者都是顶级类型,任何类型的值都可以赋值给顶级类型变量;
但是unknown比any 类型检查更严格,any什么检查都不做,unkown要求先收
通信的实现方式
一般进程通信的实现方式如下:
1、Shared Memory(内存共享);
2、Socket(套接字);
3、管道(非命名管道Pipe, 命名管道FIFO);
4、Signal(信号);
5、Message queue(消息队列);