uni-app app端(安卓实测)<editor>组件光标使用按钮插入特定符号(如【】)时定位到特定字符中间的可行方案
因为在做文本编辑器(符号快捷成对(如【】这种的)输入)需用到editor组件。
因为不能直接使用DOM,因网上搜不出解决方案,借助AI后实测出一种方案和一种待验证方案。
思路简单得离谱(主要还是对edtior这个组件不了解):
首先说一下editor
<editor> 组件底层是基于 Quill.js,所以不能使用原生输入框的 selectionStart/setSelectionRange。光标操作只能通过 Quill API 或标准 DOM API 实现。
方案一:Quill API(推荐这种)
获取 Quill 实例
const editor = document.getElementById('editor')
const quill = editor.__quill || editor.querySelector('.ql-editor')?.__quill
核心示例:插入配对符号并定位光标
例如:一个按钮直接插入【】,你需要光标在【】的中间
const range = quill.getSelection()
const pos = range ? range.index : 0
const half = Math.ceil(pair.length / 2)
quill.insertText(pos, pair)
quill.setSelection(pos + half)
优缺点
优点
- API 简洁高效
- 与编辑器状态(Delta)完全同步
- 不影响撤销/重做
缺点
- 依赖 Quill 内部属性
__quill - 不同版本 uni-app 兼容性不确定
- 需在 renderjs 中运行
方案二:原生 DOM API(降级方案:这个未验证,因为第一种方案基本解决,这是ai给的降级兜底方案)
核心思路
使用 document.createTreeWalker 遍历文本节点计算全局偏移,通过 Range + Selection API 操作光标。
获取光标全局偏移
function getCursorIndex(container) {
const sel = window.getSelection()
if (!sel?.rangeCount) return -1
const node = sel.anchorNode, off = sel.anchorOffset
if (!node || !container.contains(node)) return -1
const walker = document.createTreeWalker(container, NodeFilter.SHOW_TEXT)
let count = 0
while (walker.nextNode()) {
if (walker.currentNode === node) return count + off
count += walker.currentNode.textContent.length
}
return count
}
设置光标到指定位置
function setCursorIndex(container, index) {
const walker = document.createTreeWalker(container, NodeFilter.SHOW_TEXT)
let count = 0
while (walker.nextNode()) {
const len = walker.currentNode.textContent.length
if (count + len >= index) {
const range = document.createRange()
range.setStart(walker.currentNode, index - count)
range.collapse(true)
const sel = window.getSelection()
sel.removeAllRanges()
sel.addRange(range)
return
}
count += len
}
}
插入文本并设置光标
const text = foundNode.textContent
foundNode.textContent = text.slice(0, offset) + pair + text.slice(offset)
const range = document.createRange()
range.setStart(foundNode, offset + half)
range.collapse(true)
window.getSelection().removeAllRanges()
window.getSelection().addRange(range)
优缺点
优点
- 纯标准 DOM API,兼容性最好
- 不依赖任何框架内部属性
缺点
- 代码较复杂
- 直接改 textContent 可能破坏 Quill Delta 同步
- 富文本元素(图片等)偏移计算需额外处理
两种方案对比
代码量
- Quill API:3 行
- DOM API:30+ 行
-
Delta 同步
- Quill API:✅ 完全同步
- DOM API:❌ 可能不同步
撤销/重做
- Quill API:✅ 正常
- DOM API:❌ 可能受影响
WebView 兼容性
- Quill API:⭐⭐⭐(依赖 Quill 版本)
- DOM API:⭐⭐⭐⭐⭐
uni-app App 端实践要点
- 逻辑层无 DOM,所有 DOM 操作必须通过 renderjs 执行
- renderjs 通过
change:prop模板绑定接收逻辑层数据,通过ownerVm.callMethod()回传状态 - 方法签名:
methodName(newVal, oldVal, ownerVm, vm) - 推荐双方案:优先 Quill API → 失败则降级 DOM API
0 个评论
要回复文章请先登录或注册