{ "cells": [ { "cell_type": "markdown", "id": "fdfbe9e1", "metadata": {}, "source": [ "使用PocketView,操作Html\n", "=======================" ] }, { "cell_type": "markdown", "id": "a17a651c", "metadata": {}, "source": [ "PocketView是一个API,用于使用C#代码,用HTML的术语简明地编写HTML。就像HTML方法一样,它返回一个实现IHtmlCent的对象,因此输出将被假定为有效的HTML并呈现到您的笔记本中。这里有一个例子:" ] }, { "cell_type": "code", "execution_count": null, "id": "5859c1f7", "metadata": { "polyglot_notebook": { "kernelName": "csharp" } }, "outputs": [], "source": [ "using Microsoft.DotNet.Interactive.Formatting;\n", "using static Microsoft.DotNet.Interactive.Formatting.PocketViewTags;\n", "\n", "PocketView pocketView = PocketViewTags.span(img[src:\"https://www.baidu.com/img/flexible/logo/pc/result.png\",style:\"height:1em\"],HTML(\" \"), a[href:@\"https://www.baidu.com\"](i(\"百度\")));\n", "pocketView.Display();\n", "\n", "//display(pocketView);" ] }, { "cell_type": "markdown", "id": "ed5a269f", "metadata": {}, "source": [ "解析上面的代码:\n", "+ 调用span方法:传递三个参数,img方法结果、HTML方法结果、a方法结果;\n", "+ img方法是通过一个索引器调用的,该索引器传递了几个命名参数,src和style; \n", "+ HTML方法有一个字符串参数 ` ` 即空格的 html 转义字符;\n", "+ a方法有另一个索引器参数(href)和一个参数,在本例中是对i方法的调用;\n", "\n", "实质:以C#对象的方式,组装了一段 html代码片断" ] }, { "cell_type": "markdown", "id": "8d862b6e", "metadata": {}, "source": [ "通过将PocketView转换为字符串,您可以看到它产生的实际HTML,该字符串将以纯文本而不是HTML显示" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "polyglot_notebook": { "kernelName": "csharp" } }, "outputs": [], "source": [ "//display(pocketView.ToDisplayString());\n", "display(pocketView.ToString());" ] }, { "cell_type": "markdown", "id": "9ef8c896", "metadata": {}, "source": [ "由于HTML难以使用静态类型语言进行简洁表示,PocketView采用了动态类型。这使得你可以使用任意索引器名称来指定HTML属性。PocketViewTags上的每个方法都返回一个动态的PocketView。让我们更详细地了解你可以用PocketView实现的功能。\n", "\n", "注意:在本节的代码示例中,通过在笔记本中运行`using static Microsoft.DotNet.Interactive.Formatting.PocketViewTags`,你可以直接调用PocketView方法,而无需类名限定。\n", "\n", "如上所述,你可以使用方括号限定符来指定HTML属性,小括号填充HTML元素内容:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "polyglot_notebook": { "kernelName": "csharp" } }, "outputs": [], "source": [ "//span html片断\n", "PocketView spanElement = span[style:\"font-style:italic\"](\"你好,我带了倾斜样式\");\n", "spanElement.Display();\n", "\n", "//图片 html片断\n", "PocketView imgElement = img[src:\"https://www.baidu.com/img/flexible/logo/pc/result.png\",style:\"height:1em\", title:\"百度图片\"];\n", "imgElement.Display();\n", "\n", "//超级连接 html片断\n", "PocketView linkElement = a[href:@\"https://www.baidu.com\"](i(\"百度连接\"));\n", "linkElement.Display();" ] }, { "cell_type": "markdown", "id": "8fe067db", "metadata": {}, "source": [ "如果你将一个字符串传递给PocketView,它会为你进行HTML编码:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "polyglot_notebook": { "kernelName": "csharp" } }, "outputs": [], "source": [ "//sapn本身作为html标签,被当作Html显示;但span里的html样式的内容不被当作html渲染,而是编码后直接显示\n", "PocketView view = span(\"
对我 进行编码
\");\n", "//原样显示html片断自身,不作为html元素进行渲染\n", "display(view);\n", "\n", "//显示被html编码过的原始字符串\n", "display(view.ToString());" ] }, { "cell_type": "markdown", "id": "2376610d", "metadata": {}, "source": [ "这就是HTML方法派上用场的地方。如果你想将一个字符串传递给PocketView,但又不希望它被HTML编码,你可以简单地将该字符串用HTML方法包裹起来:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "polyglot_notebook": { "kernelName": "csharp" } }, "outputs": [], "source": [ "//HTML方法后,就作为 html片断进行 \"渲染\" 了\n", "PocketView view2 = span(HTML(\"
Don't encode me!
\"));\n", "display(view2);\n", "display(view2.ToString());" ] }, { "cell_type": "markdown", "id": "bd47366d", "metadata": {}, "source": [ "HTML简单地将一个字符串捕获到一个实现IHtmlContent接口的实例中。该接口用于指示该值不应被HTML编码,而是应被视为有效的HTML并直接呈现。\n", "\n", "了解了这一点,可能不会感到惊讶的是,PocketView本身也实现了IHtmlContent接口。\n", "\n", "你还可以将其他类型的对象传递给PocketView。当你这样做时,它们会使用纯文本格式化器进行格式化,该格式化器默认会扩展对象的属性。" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "polyglot_notebook": { "kernelName": "csharp" } }, "outputs": [], "source": [ "PocketView view3 = b(\n", " new {Fruit=\"apple\", Texture=\"smooth\"}\n", ");\n", "\n", "display(view3)" ] }, { "cell_type": "markdown", "id": "b7c66e90", "metadata": {}, "source": [ "由于目前.NET Interactive的格式化API不支持为嵌套的HTML片段生成格式化器,PocketView会回退到text/plain格式化器来描述传递对象的属性。\n", "\n", "你也可以将对象列表传递给PocketView。这对于从数据生成HTML非常有用:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "polyglot_notebook": { "kernelName": "csharp" } }, "outputs": [], "source": [ "var fruits = new []{\"apple\",\"banana\",\"cherry\"};\n", "var colors = new []{\"green\",\"#F1C40F\",\"red\"};\n", "\n", "\n", "ul(\n", " fruits.Zip(colors).Select(x => li[style:$\"color:{x.Item2}\"](x.Item1))\n", ")" ] }, { "cell_type": "markdown", "id": "cc60cd12", "metadata": {}, "source": [ "总结:其实这样的方式 \"组装\"html页面或片断,会非常繁琐;只适合临时做一些简单的html组装;\n", "方案:\n", "+ 使用 html 内核: 但有个最大问题是\"html内核不能使用共享数据\";只适合纯静态页面;\n", "+ 使用 javascript 内核: 虽然能使用 \"共享数据\"功能,但js内核长处是操作现有html并非生成html;\n", "+ 使用 razor 或 blazor 库,像razor或blazor页面或组件一样,就非常方便了;`非常推荐的终极解决方案` 唯一缺点是智能提示差,可以在VS里写好,粘贴过来哈;" ] }, { "cell_type": "markdown", "id": "20446659", "metadata": {}, "source": [ "使用 Razor的例子:体验下方不方便(后面专题讲解)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "polyglot_notebook": { "kernelName": "csharp" } }, "outputs": [], "source": [ "#r \"nuget:RazorInteractive\"" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "polyglot_notebook": { "kernelName": "razor" } }, "outputs": [], "source": [ "#!razor\n", "@{\n", " \n", " var dic = new Dictionary()\n", " {\n", " {\"apple\",\"green\"},\n", " {\"banana\",\"#F1C40F\"},\n", " {\"cherry\",\"red\"},\n", " };\n", "}\n", "\n", "" ] } ], "metadata": { "kernelspec": { "display_name": ".NET (C#)", "language": "C#", "name": ".net-csharp" }, "polyglot_notebook": { "kernelInfo": { "defaultKernelName": "csharp", "items": [ { "aliases": [], "languageName": "csharp", "name": "csharp" } ] } } }, "nbformat": 4, "nbformat_minor": 5 }