前些天,写了探索Rust编写基于web_sys的WebAssembly编辑器:挑战输入光标定位的实践,经过后续的开发检验,我发现了一个问题,就是光标消失了。为了继续输入,用户需要再次使用鼠标点击。现在我已经弄清楚了导致这个问题的原因,即需要找到text node来设置光标。
先上代码
let oninput = use_callback(
move |e: InputEvent, content1_ref1| {
if let Some((selected_str, selection, parent_element)) = get_selection_items() {
if let Some(modified_text) = parse(&selected_str) {
parent_element.set_inner_html(&modified_text); // 更新解析后的输入
selection.remove_all_ranges().unwrap(); // 移除焦点
let div = content1_ref1.cast::<HtmlDivElement>().unwrap();
div.focus();
let first_child = parent_element.first_child().unwrap().first_child().unwrap(); // 这一行是关键
let new_range = Range::new().unwrap();
new_range.set_start(&first_child, 3); // 将光标设置到第3个字符的位置
new_range.collapse();
selection.add_range(&new_range);
}
}
},
(content1_ref.clone()),
);
在上面的源代码中,我已经用注释标记了first_child
,这里是关键,因为这里获取到的就是text node。为什么一定要text node呢?原因在于range.set_start的第一个参数,参考mozilla的文档:
If the startNode is a Node of type Text, Comment, or CDataSection, then startOffset is the number of characters from the start of startNode. For other Node types, startOffset is the number of child nodes between the start of the startNode.
即如果输入的参数是text node,那么上面的那个参数3
就代表从开始到第3个字符的位置;如果是其它类型的node,就表示从开头到第3个字节点的位置。
那什么是text node呢?在web_sys中,它的类型引入就是web_sys::Text
。可以用is_instance_of::<Text>()
来判断:
if first_child.is_instance_of::<Text>() { ... }
在mozilla中,关于Text的解释如下:
The Text interface represents a text node in a DOM tree.文章来源:https://uudwc.com/A/rZAqJ
现在,我们清楚了,导致问题的原因是没有使用text node,以及在set_start方法中,如果node type不是text node,光标将如何定位。其实关于set_start的这段解释,我很早就看见了,但是由于对text node无感,就直接给忽略了。因此,才绕了这么大的一个圈子。
好了,这个小结就到这里,欢迎交流,可以想像,后面的路会更难走。文章来源地址https://uudwc.com/A/rZAqJ