fefit / visdom

A library use jQuery like API for html parsing & node selecting & node mutation, suitable for web scraping and html confusion.
MIT License
110 stars 6 forks source link

缺少类似jquery的clone #21

Closed xmh0511 closed 6 months ago

xmh0511 commented 7 months ago

测试中发现,好像没有提供jquery中对某个元素拷贝的接口,目前的cloned不是深拷贝,对返回的值进行操作依然会作用到之前的元素上

xmh0511 commented 7 months ago
use visdom::{types::BoxDynError, Vis};

fn main()->Result<(),BoxDynError> {
    const HTML:&str = r#"<div id="contain"><p class="item"></p></div>"#;
    let v = Vis::load(HTML)?;
    let p = v.find("p").get(0).unwrap().cloned();
    let mut p_clone = Vis::dom(&p);
    p_clone.set_text("abc");
    //v.find("#contain").append(& mut p_clone);
    println!("{}",v.outer_html());
    Ok(())
}

输出:

<div id="contain"><p class="item">abc</p></div>.

期望行为:

提供deep clone方法对拷贝的对象的dom的操作不影响拷贝源dom.

fefit commented 7 months ago

@xmh0511 的确 cloned() 方法是调用的 node 节点的 clone_node 方法 ,该方法只是 Rc 的一个拷贝,这个实现的确和标准语义不相符。当前库里还没有实现类似 jquery 内的 clone 方法,我打算这两天抽时间来实现一下,同时为了保证不是破坏性更改,先暂时在原基础上新增一个新方法了。

xmh0511 commented 7 months ago

也许叫 clone_dom()?既能与Rust的clone区分,也能体现jquery中clone的含义?

fefit commented 7 months ago

命名实在有点头大,想的是以后如果更新大版本直接把当前版本node节点的 clone_node 的语义改了,对应取了个 copy_node 可能会更好理解点~?对集合的操作还是实现了 clone 方法(可能容易和已有的 cloned 混淆,但将来更新版本可以不用改动),集合或者元素的 cloned 方法到时也会移除掉,另外对应元素上新增了一个 copied 方法,和node节点的 copy_node 对应,因为是打补丁的方式,所以好像都不太美观。新的代码我已经合并到主分支了,一会发布一个版本你可以试试:

const HTML:&str = r#"<div id="contain"><p class="item"></p></div>"#;
let v = Vis::load(HTML)?;
let p = v.find("p");
let mut p_clone = p.clone();
p_clone.set_text("abc");
assert_eq!(p.text(), "");
assert_eq!(p_clone.text(), "abc");
Ok(())

感谢建议与反馈~!

xmh0511 commented 7 months ago

@fefit 我认为visdom里面所有类型提供的clone接口应该都是深拷贝语义(即节点/dom的深拷贝),这一点也是Rust中clone的语义,即clone返回的值具有该值类型所表示对象的独立的所有权。如果用户想要浅拷贝,应该使用获取引用,或者通过具有指针语义的类型包装节点/dom, 比如通过Rc::new(v),Arc::new(v)等表示有多个实体共享同一个节点/dom的所有权的方式,这样也即贴合Jquery clone的语义,也符合Rust的clone语义。

fefit commented 7 months ago

@fefit 我认为visdom里面所有类型提供的clone接口应该都是深拷贝语义(即节点/dom的深拷贝),这一点也是Rust中clone的语义,即clone返回的值具有该值类型所表示对象的独立的所有权。如果用户想要浅拷贝,应该使用获取引用,或者通过具有指针语义的类型包装节点/dom, 比如通过Rc::new(v),Arc::new(v)等表示有多个实体共享同一个节点/dom的所有权的方式,这样也即贴合Jquery clone的语义,也符合Rust的clone语义。

嗯,后续如果做大版本迭代会保持这种方式了~