跳转至

自定义标签

你可以遵循 LeafTag 协议来创建自定义的 Leaf 标签。

为了演示这一点,让我们看看创建一个 #now 标签来打印当前时间戳。标签还支持一个可选参数来指定日期格式。

LeafTag

首先创建一个名为 NowTag 的类并遵循 LeafTag 协议。

struct NowTag: LeafTag {

    func render(_ ctx: LeafContext) throws -> LeafData {
        ...
    }
}

现在我们来实现 render(_:) 方法。传递给该方法的 LeafContext 参数包含了我们需要的所有内容。

struct NowTagError: Error {}

func render(_ ctx: LeafContext) throws -> LeafData {
    let formatter = DateFormatter()
    switch ctx.parameters.count {
    case 0: formatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
    case 1:
         guard let string = ctx.parameters[0].string else {
             throw NowTagError()
         }
         formatter.dateFormat = string
    default:
         throw NowTagError()
     }

    let dateAsString = formatter.string(from: Date())
    return LeafData.string(dateAsString)
}

建议

如果你的自定义标签用来渲染 HTML,你应该使你的自定义标记符合 UnsafeUnescapedLeafTag,这样 HTML 就不会被转义。别忘了检查或清除用户的任何输入。

配置标签

现在我们已经实现了 NowTag,我们只需要告诉 Leaf 就可以了。你可以像这样添加任何标签 - 即使它们来自一个单独的包。你通常在configure.swift 中做如下配置:

app.leaf.tags["now"] = NowTag()

就是这样!现在可以在 Leaf 中使用我们的自定义标签了。

The time is #now()

上下文属性

LeafContext 包含两个重要的属性。parametersdata 有我们需要的一切。

  • parameters: 包含标签参数的数组。
  • data:一个字典,包含传递给 render(_:_:) 方法作为上下文视图的数据。

Hello 标签示例

要了解如何使用它,让我们使用这两个属性实现一个简单的 hello 标签。

使用 Parameters

我们可以访问包含名称的第一个参数。

struct HelloTagError: Error {}

public func render(_ ctx: LeafContext) throws -> LeafData {

        guard let name = ctx.parameters[0].string else {
            throw HelloTagError()
        }

        return LeafData.string("<p>Hello \(name)</p>'")
    }
}
#hello("John")

使用 Data

我们可以通过使用 data 属性中的 ”name“ 键来访问 name 值。

struct HelloTagError: Error {}

public func render(_ ctx: LeafContext) throws -> LeafData {

        guard let name = ctx.data["name"]?.string else {
            throw HelloTagError()
        }

        return LeafData.string("<p>Hello \(name)</p>'")
    }
}
#hello()

控制器:

return req.view.render("home", ["name": "John"])