目录
[3.v-bind="attrs"是什么意思](#3.v-bind="attrs"是什么意思)
4.二次封装穿梭框组件,支持异步加载数据、拖拽排序怎么实现的
[🔄 实现异步加载数据](#🔄 实现异步加载数据)
[👆 实现拖拽排序](#👆 实现拖拽排序)
[🧩 组件封装技巧](#🧩 组件封装技巧)
[⚠️ 注意事项](#⚠️ 注意事项)
[💎 总结](#💎 总结)
[5.在elemnt当中,使用v-model绑定他的数据,然后再封装一次,也使用v-model的方式把数据绑定,那他里面的属性比如prefix、suffix 这些前缀和后缀,我仍然要使用他原生的一些属性 怎么实现?](#5.在elemnt当中,使用v-model绑定他的数据,然后再封装一次,也使用v-model的方式把数据绑定,那他里面的属性比如prefix、suffix 这些前缀和后缀,我仍然要使用他原生的一些属性 怎么实现?)
[💎 总结](#💎 总结)
6.localStorage、sessionStorage、cookie有什么区别
1.css的定位有哪些?
(1)静态定位(static):
- 这是元素的默认定位方式。
- 元素按照正常的文档流进行排列,忽略top、bottom、left、right和z-index属性。
(2)相对定位(relative):
-
元素先放置在未添加定位时的位置,再通过top、bottom、left、right属性使其相对于原本的位置进行移动。
-
移动后,它原本所占的空间不会改变,因此不会影响其他元素的位置。
(3)绝对定位(absolute):
-
元素脱离正常文档流,不占据空间。
-
相对于最近的非static定位的祖先元素进行定位(如果没有,则相对于初始包含块,通常是html元素)。
-
其位置由top、bottom、left、right属性确定。
(4)固定定位(fixed):
-
元素脱离正常文档流,不占据空间。
-
相对于浏览器窗口进行定位,即使页面滚动,它也会停留在固定的位置。
-
常用于导航栏、悬浮按钮等。
(5)粘性定位(sticky):
-
可以看作是相对定位和固定定位的混合。
-
元素在跨越特定阈值前为相对定位,之后为固定定位。
-
例如,可以设置一个元素在滚动到距离顶部10px时固定在那里。
2.promise
Promise 是 JavaScript 中用于处理异步操作的对象,它代表一个异步操作的最终完成(或失败)及其结果值。Promise 有三种状态:pending(进行中)、fulfilled(已成功)和rejected(已失败)。一旦状态改变,就不会再变。
(1)Promise 的基本用法:
Promise 构造函数接受一个函数作为参数,该函数的两个参数分别是 resolve
和 reject
,它们是两个函数。
-
resolve
函数将 Promise 状态从 pending 变为 fulfilled,并将异步操作的结果作为参数传递出去。 -
reject
函数将 Promise 状态从 pending 变为 rejected,并将异步操作报出的错误作为参数传递出去。
(2)Promise 的实例方法:
-
then()
: 用于指定 fulfilled 状态和 rejected 状态的回调函数。它接受两个参数,第一个是 fulfilled 状态的回调,第二个是 rejected 状态的回调(可选)。then 方法返回一个新的 Promise 实例,因此可以采用链式写法。 -
catch()
: 用于指定发生错误时的回调函数,相当于 then 的第二个参数,但 catch 可以捕获前面 then 方法执行中的错误。 -
finally()
: 用于指定不管 Promise 对象最后状态如何都会执行的操作。
(3)Promise 的静态方法:
-
Promise.resolve()
: 将现有对象转为 Promise 对象,并且状态为 fulfilled。 -
Promise.reject()
: 返回一个状态为 rejected 的 Promise 对象。 -
Promise.all()
: 用于将多个 Promise 实例包装成一个新的 Promise 实例。当所有 Promise 都成功时,返回的结果数组与传入的顺序一致;如果有一个失败,则立即返回失败的结果。 -
Promise.race()
: 同样将多个 Promise 实例包装成一个新的 Promise 实例,但是只要有一个实例率先改变状态,新的 Promise 实例的状态就跟着改变。 -
Promise.allSettled()
: 等待所有 Promise 实例都完成(不管成功还是失败),返回一个对象数组,每个对象表示对应的 Promise 结果。 -
Promise.any()
: 接收多个 Promise 实例,只要有一个变成 fulfilled 状态,就返回该 Promise 的值;如果所有都变成 rejected,则返回一个 AggregateError。
(4)错误处理: Promise 中的错误具有"冒泡"性质,直到被捕获为止。建议使用 catch 来捕获错误,而不是在 then 中写第二个参数。
(5)与回调函数相比的优点:
-
避免回调地狱,代码更清晰。
-
提供统一的错误处理机制。
(6)Promise 的局限性:
-
一旦创建无法取消。
-
如果不设置回调函数,Promise 内部抛出的错误不会反应到外部。
-
当处于 pending 状态时,无法得知当前进展到哪一个阶段。
3.v-bind="$attrs"是什么意思
$attrs
是什么?
-
$attrs
是Vue实例的一个属性,包含父组件传递给子组件 但没有在子组件props中声明的所有属性 -
包括:HTML特性、自定义属性、事件监听器等
-
不包括:在props中声明的属性、class、style
v-bind="$attrs"
的作用
将$attrs
对象中的所有属性一次性绑定到当前元素上
常用于创建包装组件,实现属性的透传
通常配合inheritAttrs: false
使用,避免重复的属性绑定
4.二次封装穿梭框组件,支持异步加载数据、拖拽排序怎么实现的
🔄 实现异步加载数据
当穿梭框需要处理大量数据时,异步加载可以有效提升性能。
-
懒加载与分页展示:
-
思路是初始只加载部分数据(如20条),通过监听列表滚动,滚动到底部时加载下一页数据 。
-
在
data
中定义pageSize
(每页条数)、curIndex
(当前页码)和showData
(当前展示的数据) 。 -
使用
v-infinite-scroll
指令(Element-UI 已提供)绑定滚动到底部的加载方法 。 -
向上滚动翻页需自行监听
scroll
事件,判断滚动条到达顶部且当前不是第一页时,加载上一页数据 。翻页时注意重置滚动条位置。
-
-
数据拼接与展示:
-
初始展示数据通过截取总数据的前
pageSize
条实现 。 -
后续加载通过数组的
slice
和concat
方法拼接新数据 。务必注意,直接展示showData
而非全部数据filteredData
。
-
👆 实现拖拽排序
为穿梭框右侧已选项列表增加拖拽排序功能,Sortable.js
是一个不错的选择。
-
使用 Sortable.js:
-
安装 Sortable.js:
npm install sortablejs
。 -
建议封装一个自定义指令(如
v-draggable-transfer
),在其mounted
钩子中,使用Sortable.create
初始化拖拽。通常只需对右侧列表(可通过类名.el-transfer-panel__list
选取,注意一般是第二个此类元素)启用拖拽 。 -
配置 Sortable 选项,如
handle
(指定拖拽触发元素,如一个拖拽图标),draggable
(指定可拖拽项),animation
(拖拽动画)等 。 -
在 Sortable 的
onEnd
回调中,通过event.oldIndex
和event.newIndex
获取拖拽前后元素位置,并调用绑定的回调函数更新数据顺序 。指令卸载时销毁 Sortable 实例 。
-
-
数据更新与视图同步:
-
在拖拽结束的回调函数中,交换
v-model
绑定数组(即右侧已选值数组)中对应oldIndex
和newIndex
的元素 。 -
Vue 是数据驱动的,数据更新后视图会自动同步。
-
-
排序与回显处理:
-
Element-UI 穿梭框的
target-order
属性会影响右侧列表排序。其默认值original
会使右侧列表顺序与数据源保持一致 。若希望按选择顺序或拖拽后顺序显示,可设置target-order
为push
或unshift
。 -
对于编辑回显,若数据源顺序与期望的右侧展示顺序不一致,可能需在回显时手动对数据源进行排序,使其与已选值数组顺序匹配 。
-
🧩 组件封装技巧
优雅地二次封装第三方组件很重要。
-
属性与事件透传:
-
使用
v-bind="$attrs"
可以将父组件传入而子组件未在props
中声明的属性绑定到内部组件 。使用v-on="$listeners"
可以透传所有事件监听器 。 -
在组件选项中设置
inheritAttrs: false
,可以避免未声明的属性被自动添加到组件的根元素上 。 -
这样封装后的组件能保持与原始 Element-UI 穿梭框相似的属性和事件使用体验。
-
-
插槽(Slot)处理:
-
若原组件使用了插槽,需要在封装组件中通过
<slot>
标签进行暴露或自定义默认内容 。 -
例如,穿梭框支持通过插槽自定义每项显示内容,封装时需在模板中保留对应插槽。
-
⚠️ 注意事项
-
性能优化:异步加载主要解决大数据量渲染的卡顿问题 。需合理设置每页加载数量。
-
拖拽目标与反馈:明确拖拽区域和触发元素,提供清晰的拖拽视觉反馈 。
-
数据一致性 :确保拖拽排序后,组件绑定的数据与视图展示保持一致。注意
target-order
属性对排序行为的影响 。
💎 总结
在面试中回答这个问题时,可以概括说明:二次封装Element-UI穿梭框,主要是通过懒加载和分页展示 优化大量数据的性能,利用 Sortable.js
实现拖拽排序 以增强交互,并运用 $attrs
和 $listeners
实现属性和事件的透传,保持组件的灵活性和易用性。清晰说明这些核心技术和思路,通常能给面试官留下良好印象。
5.在elemnt当中,使用v-model绑定他的数据,然后再封装一次,也使用v-model的方式把数据绑定,那他里面的属性比如prefix、suffix 这些前缀和后缀,我仍然要使用他原生的一些属性 怎么实现?
配置要点 | 作用和说明 | 示例或注意事项 |
---|---|---|
✅ 属性透传 | 使父组件传递的、未在子组件props 中声明的原生属性(如prefix , suffix )传递到内部组件 |
使用 v-bind="$attrs" |
✅ 事件监听器透传 | 使父组件传递的、未在子组件emits 中声明的事件监听器传递到内部组件 |
使用 v-on="$listeners" (Vue 2) 或 v-on="proxyEvents" (Vue 3) |
✅ v-model 处理 | 确保自定义组件的 v-model 与 Element 组件的 v-model 正确衔接 |
使用 modelValue 和 update:modelValue |
✅ 禁用根元素继承 | 防止未声明的属性自动添加到封装组件的根元素上 | 设置 inheritAttrs: false |
💎 总结
通过 v-bind="$attrs"
、v-on="proxyEvents"
(Vue 3) 或 v-on="$listeners"
(Vue 2) 以及正确处理 v-model
,你可以在二次封装 Element 组件时,轻松保留所有原生属性和事件。这样既保持了组件的易用性,又确保了功能的完整性。
6.localStorage、sessionStorage、cookie有什么区别
特性 | localStorage | sessionStorage | cookie |
---|---|---|---|
生命周期 | 永久,除非手动删除 | 会话级别,页面关闭则清除 | 可设置过期时间,未设置则为会话级别 |
存储大小 | 5MB | 5MB | 4KB |
与服务器通信 | 不自动发送 | 不自动发送 | 每次请求都会携带在HTTP头中 |
API易用性 | 简单 | 简单 | 需要自己封装 |
作用域 | 同源窗口共享 | 当前标签页有效 | 可设置域名和路径 |
安全性 | 不安全 | 不安全 | 可设置HttpOnly和Secure提高安全性 |
7.router的路由模式有哪几种?
(1)hash模式:
-
使用URL的hash(
#
)来模拟一个完整的URL,当URL改变时,页面不会重新加载。 -
原理:通过监听
hashchange
事件来响应路由的变化。 -
特点:hash模式下的URL会带有
#
,有些用户可能觉得不美观。但是,它兼容性好,支持所有浏览器。
(2)history模式:
-
利用HTML5 History API(pushState、replaceState、popState)来实现无刷新跳转。
-
原理:通过pushState和replaceState改变URL,且不会发送请求,然后通过popState事件来监听URL变化。
-
特点:URL没有
#
,看起来更美观。但是,需要后台配置支持,因为当用户直接访问一个路由时,如果后台没有配置该路由的对应页面,会返回404。
特性 | Hash 模式 | History 模式 | Abstract 模式 |
---|---|---|---|
URL 形式 | http://site.com/#/home |
http://site.com/home |
无 URL(内存路由) |
是否需要服务器配置 | 否 | 是 | 否 |
SEO 友好性 | 较差 | 较好 | 无 |
兼容性 | 所有浏览器 | HTML5 History API | 所有环境 |
使用场景 | 通用场景 | 需要美观URL、SEO | 非浏览器环境 |
8.vuex的核心属性有那5种?
五大核心属性:
-
State:存储应用状态数据,唯一数据源
-
Getters:计算派生状态,类似计算属性
-
Mutations:同步修改State的唯一途径
-
Actions:处理异步操作,提交Mutations
-
Modules:模块化分割大型应用状态
核心原则:
-
State是响应式的,不能直接修改
-
必须通过Mutations修改State
-
Actions处理异步,Mutations必须是同步
-
大型应用使用Modules进行模块化管理
9.Xhr、Fetch、Axios有什么区别?
(1)XHR(XMLHttpRequest)
简介:
- 是一种原生的 JavaScript API,用于发送 HTTP 请求和接收响应。
- 最早用于实现异步的 Ajax 请求。
特点:
- API 比较旧,使用起来不够直观,代码通常较为冗长。
- 支持同步和异步请求,但同步请求在现代浏览器中被逐步废弃。
优点:
- 兼容性强,支持几乎所有浏览器。
缺点:
- 不支持 Promise,需要手动处理回调逻辑,代码复杂。
补充:(2)Ajax(Asynchronous JavaScript and XML)
简介:
- 是一种技术概念,代表使用异步方式与服务器通信。
- 通常指使用 XHR 来实现异步请求的方式。
特点:
- Ajax 不是一个具体的工具,而是一种技术组合(HTML、CSS、JavaScript 和 XHR)。
优点:
- 可以加载数据到页面而无需刷新整个页面。
缺点:
- 如果基于 XHR 实现,依然存在代码冗长、缺少现代特性的问题。
(3) API
简介:
- 是现代浏览器提供的新的原生 JavaScript API,用于 HTTP 请求。
- 基于 Promise,语法更简洁,更现代化。
特点:
- 默认使用异步方式,不支持同步请求。
- 支持更丰富的功能,比如流式处理响应。
优点:
- Promise 和 async/await 支持,使代码更加直观。
- 易于扩展,比如通过拦截器对请求和响应进行处理。
缺点:
- 浏览器兼容性不如 XHR(例如旧版 IE 不支持)。
- 默认不支持超时控制,需要手动实现。
(4) Axios
简介:
- 是一个基于 Promise 的第三方 HTTP 请求库,封装了 XHR 和部分 Fetch 功能。
- 提供了更高级的功能,简化了 HTTP 请求的实现。
特点:
- 自动转换 JSON 数据。
- 支持请求和响应拦截器。
- 提供默认超时设置和更便捷的错误处理。
优点:
- 语法简单,易于使用。
- 更强大的功能(拦截器、取消请求、超时设置等)。
- 浏览器兼容性好。
缺点:
- 需要引入额外的库,增加项目体积。
10.Symbol
Symbol 是 ES6 引入的一种新的原始数据类型,表示唯一的值。主要作用是创建唯一的属性键,避免对象属性名冲突,还可以用于定义对象的私有属性,以及修改对象在特定操作下的行为(如使用内置 Symbol 值)。
-
基本概念:
-
ES6 新增的原始数据类型
-
表示唯一且不可变的值
-
主要用途是创建唯一的属性键
-
-
核心特性:
-
唯一性:每个 Symbol 都是唯一的,即使描述相同
-
不可枚举性:Symbol 属性不会被常规方法枚举到
-
全局注册表 :可以使用
Symbol.for()
创建全局共享的 Symbol
-
-
主要应用场景:
-
避免属性名冲突:在库开发中防止属性被意外覆盖
-
实现私有属性:虽然不是真正的私有,但提供了某种程度的封装
-
内置 Symbol:定义对象的默认行为(迭代、类型转换等)
-
元编程:控制对象的底层行为
-
-
常用方法:
-
Symbol(description)
- 创建 Symbol -
Symbol.for(key)
- 创建或获取全局 Symbol -
Symbol.keyFor(sym)
- 获取全局 Symbol 的键 -
Object.getOwnPropertySymbols()
- 获取对象的 Symbol 属性
-