✨✨✨目录
1.v-model的原理是什么样的?
2.Vue的生命周期?
3.Vue子组件和父组件执行顺序?
4.created和mounted的区别?
5.vue中,推荐在哪个生命周期发起请求?
6.keep-alive中的生命周期有哪些?
7.Vue组件间通信的方式?
8.Vue-Router的懒加载如何实现?
9.vue路由中,history和hash两种模式有什么区别?
10.为什么 SPA 应用都会提供一个 hash 路由,好处是什么?
11.Vue中$route和$router有什么区别?
12.如何定义动态路由?如何获取传过来的动态参数?
13.Vue-router跳转和location.href有什么区别?
14.Vue-router导航守卫有哪些?
15.对前端路由的理解?
1.v-model的原理是什么样的?
v-model
是Vue.js框架中的一个指令,用于在表单元素和组件之间实现双向数据绑定。它提供了一种简洁的方式来将表单输入的值与Vue实例的属性进行关联。
当使用v-model
指令时,Vue会根据表单元素的类型(如input
、select
、textarea
等)自动为其添加相应的事件监听器,并在用户输入时更新绑定的数据。
具体地讲,v-model
的原理如下:
在模板中,我们可以使用v-model
指令来绑定一个变量到表单元素(或组件)上,例如:<input v-model="message">;
Vue解析模板时,会将v-model
指令转换成合适的属性和事件绑定。对于大多数表单元素,它会将value
属性与输入框的当前值进行绑定,并监听input
事件来实时更新绑定的数据;
当用户在输入框中键入或选择内容时,触发input
事件。Vue会捕获该事件并更新绑定的数据,以及根据数据的变化重新渲染视图;
同样地,如果在表单元素上使用v-model
的lazy
修饰符,Vue会监听change
事件而不是input
事件。这样,只有当用户完成输入并触发change
事件时,才会更新绑定的数据。
v-model
指令实现双向绑定的原理是通过监听表单元素的输入事件(如input
或change
),将用户的输入同步到Vue实例中的属性,并在属性值变化时重新渲染视图。这使得我们可以轻松地将表单数据与Vue实例的状态保持同步,消除了手动监听和更新的冗余代码。
2.Vue的生命周期?
Vue实例有一个完整的生命周期,也就是从开始创建、初始化数据、编译模版、挂载Dom->渲染、更新->渲染、卸载等一系列过程,称这是Vue的生命周期。
(1)beforeCreate(创建前):数据观测和初始化事件还未开始,此时data的响应式追踪、event/watcher都还没有被设置,也就是说不能访问到data、computed、watch、methods上的方法和数据。
(2)created(创建后):实例创建完成,实例上配置的options包括data、computed、watch、methods等都配置完成,但是此时渲染得节点还未挂载到DOM,所以不能访问到$el属性。
(3)beforeMount(挂载前):在挂载开始之前被调用,相关的render函数首次被调用。实例已完成以下的配置:编译模板,把data里面的数据和模板生成html。此时还没有挂载html到页面
(4)mounted(挂载后):在el被新创建的vm.$el替换,并挂载到实例上去之后调用。实例已完成以下的配置:用上面编译好的html内容替换el属性指向的DOM对象。完成模板中的html染到html页面中。此过程中进行ajax交互。
(5)beforeUpdate(更新前):响应式数据更新时调用,此时虽然响应式数据更新了,但是对应的真实DOM还没有被渲染。
(6)updated(更新后):在由于数据更改导致的虚拟DOM重新渲染和打补丁之后调用。此时DOM已经根据响应式数据的变化更新了。调用时,组件DOM已经更新,所以可以执行依赖于DOM的操作。然而在大多数情况下,应该避免在此期间更改状态,因为这可能会导致更新无限循环。该钩子在服务器端渲染期间不被调用。
(7)beforeDestroy(销毁前):实例销毁之前调用。这一步,实例仍然完全可用,this仍能获取到实例。
(8)destroyed(销毁后):实例销毁后调用,调用后,Vue实例指示的所有东西都会解绑定,所有的事件监听器会被移除,所有的子实例也会被销毁。该钩子在服务端渲染期间不被调用。
3.Vue子组件和父组件执行顺序?
(1)加载渲染过程:
父组件:beforeCreate->created->beforeMount
子组件:beforeCreate->created->beforeMount->mounted
父组件:mounted
(2)更新过程:
父组件:beforeUpdate
子组件:beforeUpdate->updated
父组件:updated
(3)销毁过程:
父组件:beforeDestroy
子组件:beforeDestroy->destroyed
父组件:destroyed
4.created和mounted的区别?
在Vue中,created
和mounted
是两个常用的生命周期钩子函数,它们在组件的生命周期中扮演着不同的角色:
created:
created
是组件生命周期中的一个钩子函数,在Vue实例被创建后立即调用。- 在
created
钩子函数中,Vue实例已经完成了数据观测(data observation),但尚未渲染真实DOM。这意味着你可以访问实例中的数据、方法、计算属性等,但不能保证实例已经被插入到DOM中。 created
常用于一些初始化操作,例如数据请求、事件监听或其他非DOM相关的任务。因为此时,组件的模板还未被编译成真实DOM。
mounted:
mounted
是组件生命周期中的一个钩子函数,在Vue实例挂载到DOM后调用。- 在
mounted
钩子函数中,Vue实例已经完成了模板编译,并且已经将生成的虚拟DOM渲染到真实DOM中。 mounted
常用于需要对DOM进行操作的任务,例如初始化第三方库、绑定事件监听器、执行动画等。因为此时,组件已经被插入到DOM中,可以安全地访问和操作DOM元素。
区别总结:
created
在实例创建后被调用,适合处理数据初始化和非DOM相关的任务。
mounted
在实例挂载到DOM后被调用,适合进行DOM操作、初始化第三方库和绑定事件监听。
5.vue中,推荐在哪个生命周期发起请求?
可以在钩子函数created、beforeMount、mounted中进行调用,因为在这三个钩子函数中,data已经创建,可以将服务端返回的数据进行赋值。
推荐在mounted生命周期钩子中发起请求。理由如下:
(1)确保DOM已经被渲染
mounted钩子在组件的DOM已被插入文档之后调用。意味着所有DOM元素已存在,如果你的请求结果需要直接操作或依赖这些 DOM 元素,那么在 mounted
中发起请求是安全的。
(2)避免不必要的请求
在 created
钩子中发起请求有时会导致在组件还没有挂载时请求数据。如果组件在请求完成之前被销毁,可能会引发内存泄漏或不必要的资源浪费。因此,等待组件挂载完成再发起请求可以减少这些潜在问题。
(3)处理组件状态
在mounted钩子中发起请求,能够确保你有机会在请求开始前处理组件的状态(例如设置加载状态),并且在请求完成后更新组件的状态(例如显示数据或处理数据)
尽管mounted是推荐的生命周期钩子,但是一些特定场景可能需要在created钩子中发起请求,例如:
- SSR(服务端渲染):在服务器端渲染中,Vue实例的mounted钩子不会被调用,因为DOM并不会被真正挂载。在这种情况下,可能需要在created钩子中发起请求。
- 依赖数据初始化:如果组件在挂载之前就需要某些数据来初始化,可以在created钩子中发起请求,以确保数据在组件挂载时已经可用。
6.keep-alive中的生命周期有哪些?
keep-alive是Vue提供的一个内置组件,在组件切换时将状态保留在内存中,防止重复渲染DOM。
如果一个组件包裹了keep-alive,那么它会多出两个生命周期:deactived、activated。同时,beforeDestroy和destroyed就不会再被触发了,因为组件不会被真正销毁。
当组件被换掉时,会被缓存到内存中,触发deactivated生命周期;当组件被切回来时,再去缓存里找这个组件,触发activated钩子函数。
7.Vue组件间通信的方式?
Vue中的每一个.vue都可以视为一个组件。
组件间通信分类:父子组件之间的通信;兄弟组件之间的通信;祖孙与后代组件之间的通信;非关系组件之间的通信。
vue中常规的组件间通信方案:
(1)通过props传递
- 适用场景:父组件传递数据给子组件
- 子组件设置
props
属性,定义接收父组件传递过来的参数 - 父组件在使用子组件标签中通过字面量来传递值
(2)通过$emit触发自定义事件
- 适用场景:子组件传递数据给父组件
- 子组件通过
$emit触发
自定义事件,$emit
第二个参数为传递的数值 - 父组件绑定监听器获取到子组件传递过来的参数
(3)使用ref
- 父组件在使用子组件的时候设置
ref
- 父组件通过设置子组件
ref
来获取数据
<Children ref="foo" /> this.$refs.foo // 获取子组件实例,通过子组件实例我们就能拿到对应的数据
(4)EventBus
- 使用场景:兄弟组件传值
- 创建一个中央事件总线
EventBus
- 兄弟组件通过
$emit
触发自定义事件,$emit
第二个参数为传递的数值 - 另一个兄弟组件通过
$on
监听自定义事件
(5)$parent/$children或$root
- 通过共同祖辈
$parent
或者$root
搭建通信
兄弟组件
this.$parent.$on('add',this.add)
另一个兄弟组件
this.$parent.$emit('add')
需要注意:
- 通过$parent访问到的是上一级父组件的实例,可以使用$root来访问根组件的实例
- 在组件中使用$children拿到的是所有的子组件的实例,它是一个数组,并且是无序的
- 在根组件#app上拿$parent得到的是newVue()的实例,在这实例上再拿$parent得到的是undefined,而在最底层的子组件拿$children是个空数组
- $children的值是数组,而$parent是个对象
(6)attrs与listeners
- 适用场景:祖先传递数据给子孙
- 设置批量向下传属性
$attrs
和$listeners
- 包含了父级作用域中不作为
prop
被识别 (且获取) 的特性绑定 ( class 和 style 除外)。 - 可以通过
v-bind="$attrs"
传⼊内部组件
(7)依赖注入Provide与Inject
- 在祖先组件定义provide属性,返回传递的值
- 在后代组件通过inject接收组件传递过来的值
祖先组件
provide(){
return
{
foo:'foo'
}
}
后代组件
inject:['foo']
(8)Vuex
- 适用场景: 复杂关系的组件数据传递
Vuex
作用相当于一个用来存储共享变量的容器state
用来存放共享变量的地方getter
,可以增加一个getter
派生状态,(相当于store
中的计算属性),用来获得共享变量的值mutations
用来存放修改state
的方法。actions
也是用来存放修改state的方法,不过action
是在mutations
的基础上进行。常用来做一些异步操作
8.Vue-Router的懒加载如何实现?
非加载:
(1)(常用方式)使用箭头函数+import动态加载。
(2)使用箭头函数+require动态加载。
(3)使用webpack的require.ensure技术,也可以实现按需加载。这种情况下,多个路由指定相同的chunkName,会合并打包成一个js文件。
9.vue路由中,history和hash两种模式有什么区别?
Vue-Router有两种模式:hash模式和history模式。默认的路由模式是hash模式。
(1)hash模式
hash模式是一种把前端路由的路径用井号#拼接的真实URL后面的模式。当井号#后面的路径发生变化时,浏览器并不会重新发起请求,而是会触发hashchange事件。
使用onhashchange0事件的好处就是,在页面的hash值发生变化时,无需向后端发起请求,window就可以监听事件的改变,并按规则加载相应的代码。除此之外,hash值变化对应的URL都会被浏览器记录下来,这样浏览器就能实现页面的前进和后退。虽然是没有请求后端服务器,但是页面的hash值和对应的URL关联起来了。
优点:浏览器兼容性较好,连IE8都支持
缺点:路径在井号#后面,比较丑
(2)history模式
history API是H5提供的新特性,允许开发者直接更改前端路由,即更新浏览器URL地址而不重新发起请求。
history api可以分为两个部分,切换历史状态和修改历史状态。
- 修改历史状态:新增了pushState()和replaceState()方法,这两个方法应用于浏览器历史记录栈,提供了对历史记录进行修改的功能。
- 切换历史状态:包括forward()、back()、go()三方法,对应浏览器的前进、后退、跳转操作。
优点:路径比较正规,没有井号#
缺点:兼容性不如hash,且没有服务端支持,否则一刷新页面就404了
10.为什么 SPA 应用都会提供一个 hash 路由,好处是什么?
SPA (单页应用)采用 Hash路的核心原因在于其兼容性、性能优化及实现成本优势,具体好处如下:
(1)兼容性
Hash路由利用URL的哈希部分(即#
后的内容)实现路由切换,无需依赖 HTML5历史记录API 或服务器配置,可在所有浏览器(包括旧版本IE9及以下)中正常运行,避免了因浏览器兼容性问题导致的应用崩溃。
(2)减少服务器请求
当哈希值变化时,浏览器不会向服务器发送新页面请求,而是由JavaScript动态加载内容。这对SPA尤为重要,可避免全页刷新带来的延迟,提升用户体验。例如电商应用中切换不同视图时,仅更新局部组件而非重新加载整个页面。
(3)开发成本低
Hash路由基于浏览器原生支持,无需额外配置服务器或API支持。开发者可通过监听hashchange
事件实现路由逻辑,简化开发流程。
11.Vue中$route和$router有什么区别?
在 Vue.js 中,$route
和 $router
是 Vue Router 提供的两个不同的对象,分别用于不同的目的。
(1)$route
功能:$route
路由信息对象包含当前路由的信息,包括路径、参数、查询字符串、路由名称等
使用:用于访问当前路由的详细信息和状态。你可以从 $route
对象中获取路由参数、查询参数等。
console.log(this.$route.path); // 当前路由的路径
console.log(this.$route.params); // 路由参数
console.log(this.$route.query); // 查询字符串
(2)$router
功能:$router
路由实例对象提供了控制路由的功能,例如导航到不同的路由、替换当前路由等。
使用:用于编程式导航,控制路由的跳转。
this.$router.push('/new-path'); // 导航到新路径
this.$router.replace('/another-path'); // 替换当前路径
总结
-
$route
:提供关于当前路由的信息。 -
$router
:提供操作路由的方法,控制路由导航。
12.如何定义动态路由?如何获取传过来的动态参数?
(1)param方式
- 配置路由格式:/router/:id
- 传递的方式:在path后面跟上对应的值
- 传递后形成的路径:/router/123
- 参数获取:$route.param.id
(2)query方式
- 配置路由格式:/router,也就是普通配置
- 传递的方式:对象中使用query的key作为传递方式
- 传递后形成的路径:/route?id=123
- 参数获取:$route.query.id
两者区别:
用法:query要用path来引入,params要用name来引l入,接收参数都是类似的,分别是this.$route.query.name和this.$route.params.name。
url地址显示:query更加类似于ajax中get传参,params则类似于post,说的再简单一点,前者在浏览器地址栏中显示参数,后者则不显示。
注意:query刷新不会丢失query里面的数据params刷新会丢失params里面的数据。
13.Vue-router跳转和location.href有什么区别?
- 使用location.href=/url来跳转,简单方便,但是刷新了页面;
- 使用history.pushState(/url),无刷新页面,静态跳转;
- 引进router,然后使用router.push(/url)来跳转,使用了diff算法,实现了按需加载,减少了dom的消耗。其实使用router跳转和使用history.pushState()没什么差别的,因为vue-router就是用了history.pushState(),尤其是在history模式下。
14.Vue-router导航守卫有哪些?
- 全局前置/钩子:beforeEach、beforeResolve、afterEach
- 路由独享的守卫:beforeEnter
- 组件内的守卫:beforeRouteEnter、beforeRouteUpdate、beforeRouteLeave
15.对前端路由的理解?
前端路由是指通过JavaScript在前端实现的一种路由机制,它允许在不重新加载整个页面的情况下,根据URL的变化来更新页面内容。这种机制主要通过监听URL的变化(如hash的变化或HTML5的HistoryAPI),并在前端动态地加载和渲染相应的页面组件或内容来实现。前端路由通常用于单页面应用(SPA)中,以提供流畅的用户体验和快速的页面切换。
前端路由适合在以下场景中使用:
- 单页面应用(SPA):SPA通常只有一个HTML页面,通过前端路由可以在不刷新页面的情况下实现页面的切换和导航,从而提升用户体验。
- 需要快速响应和流畅体验的应用:前端路由可以减少页面加载时间和网络请求次数,使得页面切换更加快速和流畅。
- 需要良好SEO的应用:虽然SPA在SEO方面存在一些挑战,但通过合理的前端路由配置和服务器端渲染(SSR)等技术,可以部分解决SPA在SEO方面的问题,提高应用在搜索引擎中的可见性。
前端路由优缺点:
优点:用户体验好;更快的响应速度;更高的扩展性;实现灵活;支持单页面应用
缺点:初次加载慢;SEO不友好;增加复杂度;可维护性差
💕💕💕持续更新中......
若文章对你有帮助,点赞❤️、收藏⭐加关注➕吧!