【问题标题】:Replacing the attribute value of an htmltools::tag替换 htmltools::tag 的属性值
【发布时间】:2020-06-25 12:36:19
【问题描述】:

假设我有以下标签:

library(htmltools)

t = div(name = 'oldname')

我可以使用t$attribs$name = 'newname' 覆盖这个标签的'name' 属性,但更喜欢使用htmltools getters/setters,包是否有功能可以帮助实现这一点?

查看包手册,唯一允许对标签属性进行操作的函数是tagAppendAttributes,它只是将新的属性值附加到原来的:

t = tagAppendAttributes(t, name = 'newname')
t
#<div name="oldname newname"></div>

没有覆盖属性值的辅助函数是否意味着标签属性不应该被覆盖?

【问题讨论】:

    标签: r htmltools


    【解决方案1】:

    你可能想多了。看tagAppendAttributes的代码:

    tagAppendAttributes
    #> function (tag, ...) 
    #> {
    #>     tag$attribs <- c(tag$attribs, list(...))
    #>     tag
    #> }
    

    它所做的就是把你传递的任何东西直接写到tag$attribs。如果您 unclass 您的对象,您会发现它实际上只是一个列表:

    unclass(t)
    #> $name
    #> [1] "div"
    #>
    #> $attribs
    #> $attribs$name
    #> [1] "oldname"
    #> 
    #> 
    #> $children
    #> list()
    

    如果您具有面向对象的编程背景,我可以理解为什么直接写入对象的数据成员而不是使用 setter 可能感觉不对,但这显然是非正式 S3 类中的“公共”数据成员。直接设置它不会比任何其他实现更可能破坏它。

    如果你真的想我想你可以定义一个 setter:

    tagSetAttributes <- function(tag, ...) {tag$attribs <- list(...); tag}
    tagSetAttributes(t, name = "new name")
    #> <div name="new name"></div>
    

    【讨论】:

    • 谢谢艾伦。我对以这种方式手动设置标签 (t$attribs) 的主要担忧是,如果标签结构(即包含组件 nameattribschildren 的列表)在将来发生更改,它可能不再起作用,无论发生这种情况的机会多么渺茫。查看this discussion。使用tagAppendAttributes 之类的东西似乎是一种更安全的方法。我还想知道为什么没有属性的 setter 函数是否有原因。
    • @user51462 在 API 中似乎没有直接的方法来执行此操作,但作者现在似乎不太可能更改对象的结构。在任何情况下,仍然可以编写一个不直接访问底层列表的 setter 函数:只需编写一个 setter,它接受要重写的标记和属性,并返回具有相同类型的新节点的属性旧标签的子代减去被覆盖的新标签。这一切都可以通过提供的设置器和tag 函数来完成。
    • 这将是一个很好的解决方案,但我不确定包中提供的设置器是否允许这样做。请问可以举个例子吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-11-15
    • 2014-12-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多