Skip to content

从 1.x 升级到 2.0 ​

2.0 是一次完整重构:修复了 1.x 在注册、失效、事件上的一系列问题,统一了命名,去掉了 vue-demi。大部分页面只需要改几处写法。

暂时无法升级的项目,可以继续查阅 1.x 文档。

升级步骤 ​

  1. 确认 Vue 版本 ≥ 2.7(Vue 3 不受影响);
  2. 升级依赖:pnpm add vuepg@^2;
  3. 按下面的对照表逐项替换;
  4. 开启 debug: true 走一遍主要页面,确认焦点行为符合预期。

环境 ​

1.x2.0
支持 Vue 2.6(需 @vue/composition-api)最低 Vue 2.7
依赖 vue-demi无运行时依赖
产物为 ESNext产物为 ES2015,兼容 webpack 4
导入时用 addEventListener 监听键盘安装插件时用 addEventListener 监听键盘

安装与配置 ​

1.x2.0
app.use(vuEPG) 后调用 setConfig可直接 app.use(VuEPG, config),setConfig 仍可用
defBackHandlerbackHandler
tempBackHandler移除(内部状态,使用 onBack)
inject("epg")移除,使用 useVuEPG() 或 $epg
—新增全局属性 $epg
ts
// 1.x
const epg = useVuEPG();
epg.setConfig({ defBackHandler: () => router.back() });
app.use(vuEPG);

// 2.0
app.use(VuEPG, { backHandler: () => router.back() });

指令 ​

1.x2.0
v-epg-item="{ class: 'x' }"v-epg-item="{ focusClass: 'x' }"
—新增 disabled(item 与 group 均支持)

事件 ​

2.0 的事件都是原生 CustomEvent,并且统一加上了 epg- 前缀,避免与浏览器原生的 focus、blur 冲突(<button>、<a> 被鼠标点击时,浏览器也会派发原生 focus)。详见 事件。

1.x2.0
@focus / @blur@epg-focus / @epg-blur
@up / @down / @left / @right@epg-up / @epg-down / @epg-left / @epg-right
组的 @enter@epg-enter,焦点从组外进入时总会触发(1.x 仅在进入嵌套组时触发)
组的 @leave(未实现)@epg-leave
item 的 @enter(获得焦点时触发)移除,使用 @epg-focus
@up="":存在监听器即阻止默认移动@epg-up.prevent:显式取消;只监听不取消时照常移动
@up="epg.move(top)"@epg-up="epg.move(top)":处理函数中移动了焦点,默认移动自动跳过
方向处理函数参数为 (item, next)参数为事件对象,event.detail 为 { node, direction }
组的方向事件只检查最内层组依次检查焦点即将离开的每一层组
组的方向事件在调用 epg.move("up") 时也会触发只在按键时触发
vue
<!-- 1.x -->
<div v-epg-item @focus="onFocus" @up="">...</div>

<!-- 2.0 -->
<div v-epg-item @epg-focus="onFocus" @epg-up.prevent>...</div>

行为变化 ​

场景1.x2.0
没有焦点时按方向键以第一个注册的元素为起点移动焦点落在页面入口(default 优先)
焦点元素被隐藏 / 被 KeepAlive 缓存后按方向键不响应,焦点卡住焦点回到页面入口
移动到空组不移动焦点,不返回结果返回 false,空组不会成为目标
焦点元素重渲染(如 :class 变化)焦点 class 可能被冲掉自动补回
嵌套组件都注册了 onBack互相覆盖,子组件卸载时清空父组件的最内层优先,卸载后自动恢复
move() 等方法的返回值无boolean,表示焦点是否移动

API 对照 ​

1.x2.0
getFoucsClass()getFocusClass()
getTargetByDirection(direction)findTarget(direction)
getItemByHTMLElement(el)getNodeByElement(el) + isEPGItem()
getGroupByHTMLElement(el)getNodeByElement(el) + isEPGGroup()
getChild(el)getNodeByElement(el)
isEPGItem(el) / isEPGGroup(el)(参数为元素)isEPGItem(node) / isEPGGroup(node)(类型守卫);判断元素用 isEPGItem(getNodeByElement(el))
getGroupByItem(item)getParentGroup(item)
getParentGroupByHTMLElement(el)getParentGroup(el)
getGroupChildrenByHTMLElement(el)getChildren(group)
getGlobalGroupChildren()getChildren()
group.childrengetChildren(group)
getItemsByGroup(group)(返回元素数组)getItemsInGroup(group)(返回 EPGItem 数组)
getParentsByHTMLElement(el)移除,请直接使用 DOM API
item.isFocusgetCurrentItem() === item
dataContainer、currentConfig、keyActions、registerItem 等内部成员移除

按键 API 对照 ​

1.x2.0
getCurrentKeyActions()getKeyActions()(只读快照)
setAction(name, codes, callback, preventDefault)setKeyAction(name, { codes, callback, preventDefault })
removeAction(name)removeKeyAction(name);删除内置事件时抛出错误
setActionCallback(name, callback)updateKeyAction(name, { callback })
setActionPreventDefault(name, value)updateKeyAction(name, { preventDefault: value })
addCodeToAction(name, codes)addKeyCodes(name, codes)
removeCodeFromAction(name, codes)removeKeyCodes(name, codes)
操作不存在的事件时 console.error抛出错误
PAGEACTIONPAGE
回调参数 (code)(code, event)
ts
// 1.x
epg.setAction("ALERT", ["KeyK", 75], () => alert("K"), false);
epg.setActionPreventDefault("ALERT", true);

// 2.0
epg.setKeyAction("ALERT", { codes: ["KeyK", 75], callback: () => alert("K") });
epg.updateKeyAction("ALERT", { preventDefault: true });

弹窗与原生返回 ​

2.x 会拒绝尚未渲染的目标;设置 v-show 或挂载弹窗后,先等待 nextTick() 再移动焦点:

ts
show.value = true;
await nextTick();
epg.move(cancel.value);

旧版空方向监听器拦截移动的写法要换为 @epg-left.prevent 等明确取消事件的写法。关闭弹窗时检查原目标仍然挂载、可用,再复焦;目标失效时回到业务入口。

Android 返回桥可以直接调用 epg.back(),方向键使用 epg.navigate()。完整示例见完整示例和原生按键接入。

基于 MIT 许可发布 · 支持项目