赞
踩
key
的作用主要是为了更加高效的更新虚拟 DOM
。
Vue 判断两个节点是否相同时,主要是判断两者的key
和元素类型tag
。因此,如果不设置key
,它的值就是 undefined,则可能永远认为这是两个相同的节点,只能去做更新操作,将造成大量的 DOM 更新操作。
在 new Vue() 中,可以是函数也可以是对象,因为根实例只有一个,不会产生数据污染。
在组件中,data 必须为函数,目的是为了防止多个组件实例对象之间共用一个 data,产生数据污染;而采用函数的形式,initData 时会将其作为工厂函数都会返回全新的 data 对象。
父向子传递数据是通过props
,子向父是通过$emit
触发事件;通过父链/子链也可以通信($parent
/$children
);ref
也可以访问组件实例;provide
/inject
;$attrs
/$listeners
。
2. 兄弟组件通信:
全局事件总线EventBus
、Vuex
。
3. 跨层级组件通信:
全局事件总线EventBus
、Vuex
、provide
/inject
。
v-show
是通过给元素添加 css 属性display: none
,但元素仍然存在;而v-if
控制元素显示或隐藏是将元素整个添加或删除。v-if
切换有一个局部编译/卸载的过程,切换过程中合适的销毁和重建内部的事件监听和子组件;v-show
只是简单的基于 css 切换。v-if
是真正的条件渲染,它会确保在切换过程中条件块内的事件监听器和子组件适当地被销毁和重建,渲染条件为假时,并不做操作,直到为真才渲染。v-show
由 false 变为 true 的时候不会触发组件的生命周期;v-if
由 false 变为 true 的时候,触发组件的beforeCreate
、created
、beforeMount
、mounted
钩子,由 true 变为 false 的时候触发组件的beforeDestory
、destoryed
钩子。v-if
有更高的切换消耗;v-show
有更高的初始渲染消耗。使用场景:
如果需要非常频繁地切换,则使用v-show
较好,如:手风琴菜单,tab 页签等; 如果在运行时条件很少改变,则使用v-if
较好,如:用户登录之后,根据权限不同来显示不同的内容。
computed
计算属性,依赖其它属性计算值,内部任一依赖项的变化都会重新执行该函数,计算属性有缓存,多次重复使用计算属性时会从缓存中获取返回值,计算属性必须要有return
关键词。watch
侦听到某一数据的变化从而触发函数。当数据为对象类型时,对象中的属性值变化时需要使用深度侦听deep
属性,也可在页面第一次加载时使用立即侦听immdiate
属性。运用场景:
计算属性一般用在模板渲染中,某个值是依赖其它响应对象甚至是计算属性而来;而侦听属性适用于观测某个值的变化去完成一段复杂的业务逻辑。
Vue 2 中,v-for
的优先级比v-if
高,这意味着v-if
将分别重复运行于每一个v-for
循环中。如果要遍历的数组很大,而真正要展示的数据很少时,将造成很大的性能浪费。
Vue 3 中,则完全相反,v-if
的优先级高于v-for
,所以v-if
执行时,它调用的变量还不存在,会导致异常。
通常有两种情况导致要这样做:
v-for = "user in users" v-if = "user.active"
。这种情况,可以定义一个计算属性,让其返回过滤后的列表即可。v-for = "user in users" v-if = "showUsersFlag"
。这种情况,可以将v-if
移至容器元素上或在外面包一层template
即可。set是Vue 2中的一个全局API。可手动添加响应式数据,解决数据变化视图未更新问题。当在项目中直接设置数组的某一项的值,或者直接设置对象的某个属性值,会发现页面并没有更新。这是因为Object.defineProperty()
的限制,监听不到数据变化,可通过this.$set(数组或对象,数组下标或对象的属性名,更新后的值)
解决。
keep-alive
组件的缓存也是基于 VNode 节点的。它将满足条件的组件在 cache 对象中缓存起来,重新渲染的时候再将 VNode 节点从 cache 对象中取出并渲染。include
:字符串或正则,只有名称匹配的组件会被缓存。exclude
:字符串或正则,任何名称匹配的组件都不会被缓存。max
:数字,最多可以缓存多少组件实例。name
选项,如果name
选项不可用,则匹配它的局部注册名称(父组件 components选项的键值),匿名组件不能被匹配。如果同时使用了include
、exclude
,那么exclude
的优先级高于include
。
设置了keep-alive
缓存的组件,会多出两个生命周期钩子:activated
、deactivated
。
首次进入组件时:beforeCreate --> created --> beforeMount --> mounted --> activated --> beforeUpdate --> updated --> deactivated
再次进入组件时:activated --> beforeUpdate --> updated --> deactivated
mixin
(混入), 它提供了一种非常灵活的方式,来分发 Vue 组件中的可复用功能。
使用场景: 不同组件中经常会用到一些相同或相似的代码,这些代码的功能相对独立。可以通过mixin 将相同或相似的代码提出来。
缺点:
slot
插槽,一般在组件内部使用,封装组件时,在组件内部不确定该位置是以何种形式的元素展示时,可以通过slot
占据这个位置,该位置的元素需要父组件以内容形式传递过来。slot
分为:
默认插槽
:子组件用<slot>
标签来确定渲染的位置,标签里面可以放DOM
结构作为后备内容,当父组件在使用的时候,可以直接在子组件的标签内写入内容,该部分内容将插入子组件的<slot>
标签位置。如果父组件使用的时候没有往插槽传入内容,后备内容就会显示在页面。具名插槽
:子组件用name
属性来表示插槽的名字,没有指定name
的插槽,会有隐含的名称叫做 default
。父组件中在使用时在默认插槽的基础上通过v-slot
指令指定元素需要放在哪个插槽中,v-slot
值为子组件插槽name
属性值。使用v-slot
指令指定元素放在哪个插槽中,必须配合<template>
元素,且一个<template>
元素只能对应一个预留的插槽,即不能多个<template>
元素都使用v-slot
指令指定相同的插槽。v-slot
的简写是#
,例如v-slot:header
可以简写为#header
。作用域插槽
:子组件在<slot>
标签上绑定props
数据,以将子组件数据传给父组件使用。父组件获取插槽绑定 props 数据的方法:
<template scope="接收的变量名">
<template slot-scope="接收的变量名">
<template v-slot:插槽名="接收的变量名">
在Vue 中,修饰符处理了许多 DOM 事件的细节,让我们不再需要花大量的时间去处理这些烦恼的事情,而能有更多的精力专注于程序的逻辑处理。Vue中修饰符分为以下几种:
lazy
填完信息,光标离开标签的时候,才会将值赋予给value,也就是在change
事件之后再进行信息同步。number
自动将用户输入值转化为数值类型,但如果这个值无法被parseFloat
解析,则会返回原来的值。trim
自动过滤用户输入的首尾空格,而中间的空格不会被过滤。stop
阻止了事件冒泡,相当于调用了event.stopPropagation
方法。prevent
阻止了事件的默认行为,相当于调用了event.preventDefault
方法。self
只当在 event.target
是当前元素自身时触发处理函数。once
绑定了事件以后只能触发一次,第二次就不会触发。capture
使用事件捕获模式,即元素自身触发的事件先在此处处理,然后才交由内部元素进行处理。passive
告诉浏览器你不想阻止事件的默认行为。native
让组件变成像html
内置标签那样监听根元素的原生事件,否则组件上使用 v-on
只会监听自定义事件。left
左键点击。right
右键点击。middle
中键点击。onkeyup
,onkeydown
)的,有如下: keyCode
存在很多,但vue
为我们提供了别名,分为以下两种:
SPA(Single-page application)
,即单页面应用,它是一种网络应用程序或网站的模型,通过动态重写当前页面来与用户交互,这种方法避免了页面之间切换时打断用户体验。在SPA
中,所有必要的代码(HTML、JavaScript 和 CSS)都通过单个页面的加载而检索,或者根据需要(通常是响应用户操作)动态装载适当的资源并添加到页面。页面在任何时间点都不会重新加载,也不会将控制转移到其他页面。举个例子,就像一个杯子,上午装的是牛奶,中午装的是咖啡,下午装的是茶,变得始终是内容,杯子始终不变。SPA
与MPA
的区别:MPA(Muti-page application)
,即多页面应用。在MPA
中,每个页面都是一个主页面,都是独立的,每当访问一个页面时,都需要重新加载 Html、CSS、JS 文件,公共文件则根据需求按需加载。SPA | MPA | |
---|---|---|
组成 | 一个主页面和多个页面片段 | 多个主页面 |
url模式 | hash模式 | history模式 |
SEO搜索引擎优化 | 难实现,可使用SSR方式改善 | 容易实现 |
数据传递 | 容易 | 通过url、cookie、localStorage等传递 |
页面切换 | 速度快,用户体验良好 | 切换加载资源,速度慢,用户体验差 |
维护成本 | 相对容易 | 相对复杂 |
SPA
的优缺点:
优点:
具有桌面应用的即时性、网站的可移植性和可访问性
用户体验好、快,内容的改变不需要重新加载整个页面
良好的前后端分离,分工更明确缺点:
不利于搜索引擎的抓取
首次渲染速度相对较慢
v-model
,可以绑定一个响应式数据到视图,同时视图的变化能改变该值。v-model
是语法糖,默认情况下相当于:value
和@input
,使用v-model
可以减少大量繁琐的事件处理代码,提高开发效率。v-model
,还可以在自定义组件上使用,表示某个值的输入和输出控制。v-model
是一个指令,双向绑定实际上是Vue 的编译器完成的,通过输出包含v-model
模版的组件渲染函数,实际上还是value
属性的绑定及input
事件监听,事件回调函数中会做相应变量的更新操作。prop
都遵循着单项绑定原则,props
因父组件的更新而变化,自然地将新状态向下流往子组件,而不会逆向传递。这避免了子组件意外修改父组件的状态的情况,不然应用的数据流将很容易变得混乱而难以理解。props
都会被更新为最新值,这就意味着不应该子组件中去修改一个prop
,若这么做了,Vue 会在控制台上抛出警告。prop
:
prop
被用于传入初始值,而子组件想在之后将其作为一个局部数据属性。这种情况下,最好是新定义一个局部数据属性,从props
获取初始值即可。prop
值做进一步转换。最好是基于该prop
值定义一个计算属性。emit
一个事件让父组件变更。当对象或数组作为props
被传入时,虽然子组件无法更改props
绑定,但仍然可以更改对象或数组内部的值。这是因为JS的对象和数组是按引用传递,而对于 Vue 来说,禁止这样的改动虽然可能,但是有很大的性能损耗,比较得不偿失。$router
是VueRouter的实例对象,是一个全局的路由对象,包含了所有路由的对象和属性。$route
是一个跳转的路由对象,可以认为是当前组件的路由管理,指当前激活的路由对象,包含当前url解析得到的数据,可以从对象里获取一些数据,如:name,path,params,query等。router-link
:<router-link :to="'/users?userId:1'"></router-link>
<router-link :to="{ name: 'users', params: { userId: 1 } }"></router-link>
<router-link :to="{ path: '/users', query: { userId: 1 } }"></router-link>
router-push
:
params
传参this.$router.push({
name: 'users',
params: {
userId: 1
}
});
// 路由配置
{
path: '/users',
name: 'users',
component: User
}
// 跳转后获取路由参数
this.$route.params.userId // 为 1
* 通过`query`传参
this.$router.push({
path: '/users',
query: {
userId: 1
}
});
// 路由配置
{
path: '/users',
name: 'users',
component: User
}
// 跳转后获取路由参数
this.$route.query.userId
* 动态路由
this.$router.push('/users/${userId}');
// 路由配置
{
path: '/users/:userId',
name: 'users',
component: User
}
// 跳转后获取路由参数
this.$route.params.userId
location.hash
的值就是url中 #
后面的东西。它的特点在于:hash虽然出现url中,但不会被包含在HTTP请求中,对后端完全没有影响,因此改变hash不会重新加载页面。window.addEventListener("hashchange", funcRef, false)
,每一次改变hash (window.location.hash)
,都会在浏览器的访问历史中增加一个记录,利用hash的以上特点,就可以实现前端路由更新视图但不重新请求页面的功能了。pushState()
和replaceState()
方法。back
、forward
、go
的基础上(使用popState()
方法),他们提供了对历史记录进行修改的功能。很多时候,我们需要将给定匹配模式的路由映射到同一个组件,这种情况就需要定义动态路由。例如,我们有一个 User组件,对于所有 ID 各不相同的用户,都要使用这个组件来渲染。那么,我们可以在 vue-router 的路由路径中使用动态路径参数(dynamic segment)
来达到这个效果:{path: '/user/:id', compenent: User}
,其中:id
就是动态路径参数。
state
对象中,它本身是一颗状态树,组件中使用store
实例的state
访问这些状态;然后用配套的mutation
方法修改这些状态,并且只能用mutation
修改状态,在组件中调用commit
方法提交mutation
;如果应用中有异步操作或复杂逻辑组合,需要编写action
,执行结束如果有状态修改仍需提交mutation
,组件中通过dispatch
派发action
。最后是模块化,通过modules
选项组织拆分出去的各个子模块,在访问状态(state)时需注意添加子模块的名称,如果子模块有设置namespace
,那么提交mutation
和派发action
时还需要额外的命名空间前缀。Vuex 只是在内存中保存状态,刷新后就会丢失,如果要持久化就需要保存起来。
localStorage
就很合适,提交mutation
的时候同时存入localStorage
,在store
中把值取出来作为state
的初始值即可。
也可以使用第三方插件,推荐使用vuex-persist
插件,它是为 Vuex 持久化储存而生的一个插件,不需要你手动存取storage
,而是直接将状态保存至 cookie
或者 localStorage
中。
SSR
即服务端渲染(Server Side Render)
,就是将 Vue 在客户端把标签渲染成 html 的工作放在服务端完成,然后再把 html 直接返回给客户端。
keep-alive
缓存页面。避免重复创建组件实例,且能保留缓存组件状态。v-for
遍历避免同时使用v-if
。实际上在 Vue 3 中已经是一个错误用法了。v-once
。不再变化的数据使用v-once
。js前端的重头戏,值得花大部分时间学习。
推荐通过书籍学习,《 JavaScript 高级程序设计(第 4 版)》你值得拥有。整本书内容质量都很高,尤其是前十章语言基础部分,建议多读几遍。
另外,大推一个网上教程 现代 JavaScript 教程 ,文章深入浅出,很容易理解,上面的内容几乎都是重点,而且充分发挥了网上教程的时效性和资料链接。
学习资料在精不在多,二者结合,定能构建你的 JavaScript 知识体系。
面试本质也是考试,面试题就起到很好的考纲作用。想要取得优秀的面试成绩,刷面试题是必须的,除非你样样精通。
这是288页的前端面试题
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。