选择器

CSS选取器分类 通配符选择器 *{ margin:0; padding:0; } 元素(标签)选择器 p{ color:red; } 类选择器 .warning{ color:red; } ID选择器 #warning{ color:red; } 优先级 !important>行内样式>ID选择器>类、伪类、属性>元素、伪元素>继承>通配符 属性选取器 示例html <ul> <li foo>1</li> <li foo="abc">2</li> <li foo="abc efj">3</li> <li foo="abcefj">4</li> <li foo="efjabc">5</li> <li foo="ab">6</li> </ul> [attribute] [foo]{ background-color:red; } 选择所有带 foo 属性的元素 [attribute=value] 选择 attribute=value 的所有元素。 [foo=abc]{ background-color:red; } [attribute~=value] 选择 attribute 属性包含单词 value 的所有元素。 [foo~=abc]{ background-color:red; } [attribute^=value] 选择其 attribute 属性值以 value 开头的所有元素。类似正则的 ^,以什么开始 ...

October 8, 2024

任务自动化

在前端开发中,我们经常需要执行各种重复性任务,比如编译代码、启动本地服务器、监听文件变化、运行测试、部署代码等。虽然可以使用不同的工具来完成这些任务,但npm本身提供了一个强大的功能:npm scripts。通过npm scripts,我们可以将这些任务脚本化并集中管理,从而提高开发效率。本文将专注于如何使用npm scripts自动化前端开发任务,以及它在项目管理中的作用。 什么是npm scripts? npm scripts是npm提供的一种机制,允许我们在项目的package.json文件中定义一组命令,方便执行各种任务。在package.json文件中,scripts字段可以包含多个脚本,每个脚本都是一个键值对,其中键是脚本的名称,值是实际要执行的命令。例如: { "scripts": { "build": "webpack --config webpack.config.js", "test": "jest" } } 在上面的示例中,定义了两个脚本:build 和 test。可以通过以下方式在命令行中运行这些脚本: npm run build npm run test npm会执行对应的命令,自动帮我们完成编译和测试任务。 为什么使用npm scripts? 在现代前端开发流程中,自动化任务是不可或缺的,而npm scripts的使用有以下几大优势: 减少对全局依赖的需求:在传统项目中,开发者通常需要全局安装各种命令行工具,如webpack、eslint、babel等。而npm scripts可以直接调用项目的本地依赖,无需全局安装。这确保了不同开发环境中的工具版本一致,减少了版本冲突和兼容性问题。 集中管理任务:npm scripts将所有任务定义集中在package.json文件中,项目中的所有开发人员都可以直观地看到可用的任务列表,无需了解每个工具的详细使用方法。只需运行npm run <task>,便可一键完成常见任务。 支持跨平台执行:npm scripts中的命令可以跨平台使用,在Windows、macOS和Linux系统上表现一致,尤其适合团队协作。 便于组合和链式执行:npm允许通过逻辑操作符来组合脚本,实现复杂任务的自动化执行。例如可以通过&&和||来串联多个任务,使得多个步骤一次完成。 如何定义和使用npm scripts? 让我们通过具体的示例来看看npm scripts如何自动化前端开发任务。 1. 设置基本的开发任务 假设我们正在开发一个React项目,我们可以在package.json中定义以下基本任务: { "scripts": { "start": "webpack serve --mode development", "build": "webpack --mode production", "test": "jest", "lint": "eslint src/**/*.js" } } 这里的脚本分别执行以下任务: ...

October 5, 2024

vue指令

1.1 钩子函数 一个指令定义对象可以提供如下几个钩子函数 (均为可选): bind 只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置。 inserted 被绑定元素插入父节点时调用 (仅保证父节点存在,但不一定已被插入文档中)。 update 所在组件的 VNode 更新时调用,但是可能发生在其子 VNode 更新之前。指令的值可能发生了改变,也可能没有。 componentUpdated 指令所在组件的 VNode 及其子 VNode 全部更新后调用。 unbind 只调用一次,指令与元素解绑时调用。 Vue.directive('gqs',{ bind() { // 当指令绑定到 HTML 元素上时触发.**只调用一次** console.log('bind triggerd') }, inserted() { // 当绑定了指令的这个HTML元素插入到父元素上时触发(在这里父元素是 `div#app`)**.但不保证,父元素已经插入了 DOM 文档.** console.log('inserted triggerd') }, updated() { // 所在组件的`VNode`更新时调用. console.log('updated triggerd') }, componentUpdated() { // 指令所在组件的 VNode 及其子 VNode 全部更新后调用。 console.log('componentUpdated triggerd') }, unbind() { // 只调用一次,指令与元素解绑时调用. console.log('unbind triggerd') } }) 1.2 钩子函数参数 指令钩子函数会被传入以下参数: ...

October 4, 2024

https

阅读本文之前,咱们先来看几道面试题: 什么是HTTPS? HTTPS改进HTTP存在的哪些问题? HTTPS加密原理是什么? 什么是对称加密和非对称加密? HTTPS传输过程? 什么是数字证书?为什么需要数字证书? 为什么需要数字签名? … 如果你能准确无误的回答以上问题,你可以不用继续往下面看了,如果不能,通过阅读这篇文章,我相信你肯定能完全掌握HTTPS。好了废话不多说,我们开始。 什么是 HTTPS 当我们在访问一个地址采用HTTPS协议的Web网站时,浏览器的地址栏内会出现一个带锁的标记,就像这样: 我们想要了解一个东西之前,我们得先知道它是什么,那么HTTPS是什么呢? 可能很多同学都能说道说道:“HTTPS就是能够给我们的请求加密的一个东西”。的确,我们都知道,HTTPS可以加密,但是很多同学的理解仅限于此,无法深层次的理解HTTPS。那么到底什么是HTTPS? HTTPS是在HTTP上建立SSL加密层,并对传输数据进行加密,是HTTP协议的安全版。 说得再简单一点,HTTPS就是 HTTP + SSL: 哦明白了,原来HTTPS就是“披着羊皮的狼”啊。HTTP你肯定是理解的,如果不理解,建议先去阅读HTTP相关知识。 那SSL又是什么呢? 我们都知道,HTTP是应用层的协议,HTTP是直接和TCP通信的,当我们更换为HTTPS的时候,它就演变成了,先和SSL通信、然后再由SSL和TCP通信了。知道了这一流程,我们思考一下,加密过程是在哪个过程进行的? 结果很显然,加密过程就是在HTTP->SSL这一阶段实现的,所以SSL简单来说,就是实现HTTP的加密过程: 对称加密和非对称加密、散列函数这些又是啥啊?没事后面会讲,这些概念你先记住咯。 HTTPS 有什么用 在讲明HTTPS的作用之前,我们先来看看HTTP有哪些弊端: 和服务器通信时,直接采用明文传输,那么明文内容有可能被挟持监听和篡改 由于HTTP本身不具备加密的功能,所以无法做到对通信内容进行加密。也就是说,我们传输的方式,都是直接以明文的形式进行传输,这些明文数据会经过中间代理服务器、路由器、wifi热点、通信服务运营商等多个物理节点,相当于所有通信的数据都在网络中裸奔,想想都刺激。 那么显而易见,明文传输有什么缺陷呢?明文传输可能会导致数据泄露、数据篡改、流量劫持、钓鱼攻击等一系列危险。假设有这么一个场景,某一天,你的另一个女朋友过生日,于是你用浏览器登录了你的邮箱,想给她发送一封生日祝福的邮件。假如这个邮箱网站使用的是HTTP协议,当你点击发送的时候,你的“祝福内容”(注意:是明文),被某个黑客拦截到,然后将这份“祝福内容”直接转发到你的“现任女朋友”,那后果简直不堪设想。 和服务器通信时,无法验证身份 使用HTTP发起请求时,服务器不会验证请求方的身份,响应请求时,请求方也不会验证服务方的身份。说简单点就是,任何人都可以发起请求,同时,服务器只要接收到请求,不管对方是谁都会返回一个响应。所以任何人都可以伪造虚假服务器欺骗用户,实现“钓鱼欺诈”,用户无法察觉,这也是为啥以前我们的qq号老是被盗的原因。 了解到HTTP这些缺陷之后,我们就自然知道了HTTPS到底有什么用: 保证数据的安全性(加密我们的明文数据) 保证数据的完整性 身份认证 HTTPS如何加密(SSL过程) 通过上面的内容,我们知道了HTTPS能够对数据进行加密,那么它具体是如何加密的呢? 这里我们需要先了解两种加密方式: 对称加密 非对称加密 别觉得它们会有多么难理解,心中坚信,一切计算机网络的知识都是纸老虎。 什么是对称加密 那么什么是对称加密呢? 简单说就是有一个密钥,它可以加密数据,也可以对加密后的数据进行解密。试想有这样一个场景:两个港口需要运送一批货物,发货方发货时,将货物装进集装箱并用一把锁将集装箱锁起来,收货方收到货物时,需要用同样的钥匙(不一定是同一把)将集装箱打开,从而取出货物。 所以简单来说,对称加密就是通信双方都有一把同样的钥匙,用于打开同一个集装箱(解密),从而获取数据的一种方式: HTTPS用对称加密可行吗 如果通信双方(浏览器和服务器)都各自拥有同样的私钥,在发送方发送数据之前,将数据锁(加密)起来,然后接收方再用私钥解锁(解密),这样就能完美的保证通信的安全。但是关键的问题就在于,在通信之前,服务器或者浏览器如何同时拥有一把同样的私钥呢?我们来想想办法: 1、服务器给浏览器传输私钥 当浏览器发起请求到服务器时,服务器生成一个私钥,然后传输给浏览器,浏览器拿到之后,他们正式通信就开始用这一个私钥进行加密通信,不就行了?那么问题又来了,假设在传输私钥本身的过程中,被中间人挟持了怎么办?中间人拿到私钥之后,就可以解密通信双方的加密内容了,所以这样做肯定是不可行的。 2、在浏览器里面预留服务器提供的私钥。如果我们浏览器一开始就预留了目标网站的私钥,那这样通信的时候,就只有天知地知你知我知了,这不就行了?但是问题的关键是,世界上的网站千千万,浏览器要预留全部HTTPS协议网站的私钥,这显然不可能啊。 很显然,以上两种假设,都不能实现我们想要的加密效果,所以对称加密暂时被我们 pass. 什么是非对称加密 既然对称加密不行,那么我们就需要考虑非对称加密了,那非对称加密又是什么呢? 我们还是来看看还是刚刚上面👆那个运送货物的例子: 两个港口需要运送一批货物,发货方发货时,将货物装进集装箱并用一把锁(我们将其称为公钥)将集装箱锁起来,收货方收到货物时,需要用另外一把钥匙(我们将其称为私钥)将集装箱打开,从而取出货物。 注意这里的关键是:当通信的一方使用公钥时,另外一方只能使用私钥,反之亦然。 简单的来说就是有两把密钥,一把叫做公钥、一把叫私钥。用公钥加密的内容必须用私钥才能解开,同理,私钥加密的内容只有公钥能解开。公钥对于私钥来说是非对称的,所以我们把这种加密方式称为非对称加密: HTTPS用非对称加密可行吗 我们利用非对称加密来模拟一下浏览器和服务器通信的过程。 浏览器向服务器发起请求,服务器收到请求之后,将公钥传输给浏览器,然后在接下来的通信中,浏览器要向服务器发送数据时,先用公钥将数据加密,然后发送给服务器,服务器收到之后,再用对应的私钥进行解密,这样就保证了浏览器->服务器这条路的数据安全。因为浏览器发送给服务器的数据,只有服务器有私钥能够解密它。那么反过来,服务器->浏览器这条路的通信是否安全呢? 捋一捋刚刚的过程,我们就会发现,一开始我们的服务器将公钥传输给浏览器这一步骤,显然是在明文形式下进行传输的。假设这一过程,我们的公钥被中间人挟持了,想想会发生什么情况?显然有了这个公钥,中间人就能解密由服务器利用私钥加密的数据了,虽然他不能解密浏览器端的数据,但是此时他可以伪造请求,服务器收到请求之后,利用私钥解密请求数据,之后响应请求,并用私钥对响应数据加密,接着返回给请求方,由于此时这个中间人是有对应的公钥的,所以他就能直接解密服务器返回的数据。 ...

October 2, 2024

默认参数

一、参数传递 代码语言:javascript function foo(a, b) { console.log([a, b]); } foo(1, 2); // 输出 [1, 2] 这个例子中,a 和 b 属于函数中的局部变量,只能在函数中访问。调用函数时,传递的数据会根据位置来匹配对应,分别赋值给 a 和 b。 创建函数时,function 函数名 后面括号中设定的参数被称为形参;调用函数时,函数名后面括号中传入的参数被称为实参。上面例子中,a 和 b 是形参,传入的 1 和 2 是实参。 因为形参是已声明的变量,所以不能再用 let 和 const 重复声明。 代码语言:javascript function foo(a, b) { let a = 1; // 报错,a 已声明 const b = 1; // 报错,b 已声明 } JavaScript 中所有函数传递都是按值传递的,不会按引用传递。所谓的值,就是指直接保存在变量上的值,如果把对象作为参数传递,那么这个值就是这个对象的引用,而不是对象本身。这里实际上是一个隐式的赋值过程,所以给函数传递参数时,相当于从一个变量赋值到另一个变量。 原始值: 代码语言:javascript function add(num) { return num + 1; } let count = 5; let result = add(count); // 此处参数传递的过程可以看作是 num = count console.log(count); // 5 console.log(result); // 6 引用值: ...

October 2, 2024

语义化

HTML 语义化是什么? HTML 语义化是指使用 HTML 标签来正确地表示文档的结构和内容的方式。通过使用正确的标签和元素,可以使网页的结构更加清晰、易于理解,并且对搜索引擎和辅助技术(如屏幕阅读器)更友好。 CSS 命名的语义化指的是在给 CSS 类名、选择器和 ID 命名时,使用具有语义的名称来描述元素的用途和功能。这样的命名方式可以使代码更具可读性、可维护性和可拓展性。 为什么需要语义化? 有利于搜索引擎优化(SEO):搜索引擎依赖于网页的结构和语义来识别和理解网页内容。使用语义化的 HTML 标签可以提高网页在搜索引擎结果的排名,从而提高页面的 SEO(搜索引擎优化)。 可读性和可维护性:使用语义化的代码可以增强代码的可读性和可维护性,有利于开发人员理解和维护代码。同时,遵循 W3C 标准的团队可以遵循相同的标准,减少差异化,提高团队的效率和协调能力。 提高可访问性:语义化可以提高网页的可访问性,让页面更容易被搜索引擎、辅助技术(如屏幕阅读器)解析和理解,让更多的人能访问和理解网页。 可间接提升网页的性能:在传统的 HTML 代码中,有时候会存在一些重复的标签和属性,导致代码冗余。使用语义化的 HTML 代码,可以减少这种冗余,让代码更加简洁和高效。 面向未来的 HTML ,浏览器在未来可能提供更丰富的支持。 一些常用的语义化标签及使用场景 布局相关的语义化标签: <header> 标签:用于定义文档或一个节的头部区域。通常包含网页的标题、导航栏、logo 或其他相关信息;作用是为页面提供附加的信息或功能,以帮助用户更好地理解或导航网页内容。适用于表示网页或一个节的顶部区域。 <aside> 标签:用于定义与页面内容相关但可以被视为独立于主要内容的部分。它通常用于侧边栏、广告、导航链接、附加信息或其他类似的内容。 <section> 标签:用于表页面中的一个独立部分,具有明确的主题或目的。例如文章、评论、产品列表、产品规格及描述等。一个页面可以包含多个不同主题的 section ;并且这个标签可以包含标题、段落、列表、表格等其他HTML元素。 <nav> 标签:用于表示导航菜单,包括主导航、子导航、面包屑导航等。这个标签通常包含链接(<a> 标签)来指向其他页面或网站的部分。 <footer> 标签:用于表示文档的页脚,通常包含版权信息、联系方式、法律声明等内容。它通常出现在页面的底部,并且只应该出现一次。 <main> 标签:用于表示页面中的主要内容区域,是所有主要内容(包括头部、尾部和侧边栏)的容器。每个<main>元素都应该包含独特的内容,这部分内容在页面上是唯一的,且对整个页面来说是重要的。<main>标签不能包含在页面其它区块元素中,通常是<body>的子标签,或者是全局<div>的子标签。 <address> 标签:用于表示联系信息,通常包含地址、电子邮件地址、电话号码等。这个标签通常用于定义页面或其部分内容的作者或拥有者的联系信息。 举个栗子🌰: <body> <!-- 页面的头部 --> <header> <h1>欢迎来到我的网站</h1> <p>这是网站的标题,用于展示网站的核心信息。</p> </header> <!-- 导航菜单 --> <nav> <ul> <li><a href="#">首页</a></li> <li><a href="#">关于我们</a></li> <li><a href="#">产品</a></li> <li><a href="#">联系我们</a></li> </ul> </nav> <!-- 主要内容区域 --> <main> <!-- 第一个内容区块 --> <section></section> <!-- 第二个内容区块 --> <section> <aside></aside> <aside></aside> </section> </main> <!-- 联系信息 --> <address> <p><strong>联系信息:</strong></p> <p>电话:(123) 456-7890</p> <p><a href="mailto:example@email.com">example@email.com</a></p> </address> <!-- 页面的底部 --> <footer> &copy; 2023 My Website. All rights reserved. | 设计:北冥有锅 </footer> </body> 文本相关语义化标签: figure 和 figcaption、del 和 ins <figure> 标签:用于处理带有某些嵌入式内容的一组图,照片,代码清单等。表示独立的内容单元,它可以包含任何与主内容相关的附加内容,包括但不限于:文本内容、媒体文件、交互式内容等。使用<figure>标签时应当注意内容的独立性和相关性,确保它与主内容是相关的,并且不依赖于主内容而存在。 <figcaption> 标签:<figcaption>标签是<figure>元素的一部分,并且它是可选的。它应该包含在<figure>标签内部,作为其第一个或最后一个子元素。一个<figure>标签中只能有一个<figcaption>标签。 <del> & <ins> 标签: <del> 用作已删除内容的标签。浏览器通常通过在已删除的文本上打一行删除线来呈现它。 <ins> 用于表示HTML文档中新添加的文本。它通常在文本上带有下划线。 <ins> 与<del> 一起使用时更有用,他们都可以使用CSS属性进行更改。 <ins> 与<del> 的特定属性: cite:URL => 它指定资源的URL,该URL解释更改或删除文本的原因。 datetime:YYYYMMDD || HH:MM:SS => 它指定更改或删除文本的日期和时间。 举个栗子🌰: ...

September 24, 2024

FoundationModels

2025年WWDC上,Apple把Apple Intelligence背后的那个"设备端基础模型"第一次对开发者开放——这就是FoundationModels框架。过去要在App里接入LLM,基本只有两条路:调OpenAI/Claude这类云端API,或者自己在端上集成llama.cpp、MLC、Core ML等推理框架。前者有隐私和成本问题,后者有工程门槛和包体积问题。FoundationModels试图提供第三条路:一个系统级的、免费的、离线可用的、原生Swift的LLM API。 本文从框架定位开始,一路讲到Guided Generation、Tool Calling、Streaming、Adapter微调等细节,目标是让你在读完后能直接上手用它写出一个生产可用的功能。 一、FoundationModels是什么 1.1 一句话定义 FoundationModels是iOS 26 / macOS 26及之后的系统框架,提供对设备端Apple Intelligence语言模型的编程访问能力。模型本身约3B参数,经过4-bit量化,常驻系统,不计入App包体积,所有推理在设备上完成。 1.2 能做什么 / 不能做什么 能做 不能做 文本生成、摘要、分类、抽取、改写、翻译 世界知识问答(模型太小,不适合当"百科") 结构化输出(生成指定Swift类型) 图像生成 / 视频生成 工具调用(Function Calling) 嵌入向量生成(Embedding) 短对话、小规模推理 长上下文的复杂推理(窗口有限) 完全离线、无需联网 替代GPT-4这类前沿大模型 定位非常清楚:它是一个"端侧小而美"的模型,负责那些没必要上云、对延迟/隐私/成本敏感的任务。 1.3 为什么值得iOS开发者关注 零成本:不像调OpenAI API,每token都花钱。 零延迟网络层:首token延迟可以做到100ms级。 隐私合规:输入不出设备,符合医疗、金融、教育场景的合规要求。 离线可用:地铁、飞机、隧道里也能跑。 原生Swift DSL:宏驱动的@Generable、Tool协议,跟SwiftUI一样"声明式"。 与系统深度集成:可直接访问Apple Intelligence上下文(比如屏幕识别、个人数据等,受权限约束)。 二、整体架构 graph TB subgraph APP ["应用层"] UI["SwiftUI / UIKit"] VM["ViewModel"] end subgraph FM ["FoundationModels Framework"] SLM["SystemLanguageModel模型句柄 + 可用性"] SESSION["LanguageModelSession会话对象 / 上下文"] GEN["Generable宏结构化输出"] TOOL["Tool协议工具调用"] STREAM["ResponseStream流式输出"] GUARD["Guardrails安全过滤"] end subgraph SYSTEM ["系统层"] ANE["Apple Neural Engine"] GPU["GPU"] MODEL["On-device Foundation Model≈3B params, 4-bit quant"] ADAPTER["LoRA Adapters"] end UI --> VM VM --> SESSION SESSION --> SLM SESSION --> GEN SESSION --> TOOL SESSION --> STREAM SESSION --> GUARD SLM --> MODEL MODEL --> ANE MODEL --> GPU ADAPTER --> MODEL 几个关键抽象: ...

May 2, 2026

KVC底层原理

基础概念 KVC(Key-Value Coding,键值编码)是 Apple 提供的一种通过字符串 key 间接访问对象属性的机制,定义在 NSKeyValueCoding 协议中,NSObject 默认遵循该协议。 // 直接访问 person.name = @"Tom"; NSString *name = person.name; // KVC 访问 [person setValue:@"Tom" forKey:@"name"]; NSString *name = [person valueForKey:@"name"]; KVC 的核心价值在于:通过字符串动态访问属性,不需要在编译期知道属性名。这使得字典转模型、序列化/反序列化、Interface Builder 的 Runtime Attributes 等场景成为可能。 setValue:forKey: 的底层流程 当调用 [obj setValue:value forKey:@"name"] 时,Runtime 按照以下顺序查找: flowchart TD A["setValue:forKey:@'name'"] --> B{"查找 setter 方法"} B -->|"找到"| C["调用 setter"] B -->|"未找到"| D{"accessInstanceVariablesDirectly返回 YES?"} D -->|"YES"| E{"按顺序查找实例变量_name → _isName → name → isName"} D -->|"NO"| F["调用 setValue:forUndefinedKey:默认抛出 NSUndefinedKeyException"] E -->|"找到"| G["直接设置实例变量值"] E -->|"未找到"| F 第一步:查找 setter 方法 Runtime 按以下顺序查找 setter 方法: ...

May 2, 2026

WebView离线包

背景 Hybrid 开发模式下,WebView 加载 H5 页面的体验一直是痛点。一个典型的 H5 页面加载流程涉及:初始化 WebView -> DNS 解析 -> 建立连接 -> 下载 HTML -> 解析 HTML -> 下载 CSS/JS/图片 -> 渲染页面。在弱网或首次加载场景下,白屏时间常常达到 2~5 秒,远不如 Native 体验。 离线包的核心思路是:将 H5 的静态资源(HTML、CSS、JS、图片、字体等)预先打包下发到客户端本地,WebView 加载时直接从本地读取资源,跳过网络请求环节,从而大幅缩短页面加载时间。 离线包加载 vs 在线加载 sequenceDiagram participant App participant WebView participant Local as 本地离线包 participant Server as 远程服务器 Note over App, Server: 在线加载流程 App->>WebView: loadURL WebView->>Server: DNS + TCP + TLS + HTTP请求 Server-->>WebView: HTML WebView->>Server: 请求 CSS/JS/图片 Server-->>WebView: 资源文件 WebView->>WebView: 渲染页面 Note over App, Server: 离线包加载流程 App->>WebView: loadURL(被拦截) WebView->>Local: 读取本地 HTML Local-->>WebView: HTML WebView->>Local: 读取本地 CSS/JS/图片 Local-->>WebView: 资源文件 WebView->>WebView: 渲染页面 对比项 在线加载 离线包加载 首屏时间 2~5秒(弱网更久) 0.5~1秒 网络依赖 强依赖 仅更新时需要网络 白屏问题 严重 基本消除 资源新鲜度 实时最新 有一定延迟 流量消耗 每次访问都消耗 仅增量更新消耗 整体架构 一个完整的离线包系统包含三大部分: ...

May 2, 2026

动态化 DSL 详解

动态化 DSL(Domain-Specific Language,领域特定语言)是"不改 App 主包、不走应用商店审核,只下发一段描述文件就能改变界面和逻辑"的一类技术。它在 2015~2023 年成为国内大厂客户端的必备基础设施:阿里 DinamicX / Tangram / VirtualView / LuaView、字节 Lynx、腾讯 Mars / 小程序、滴滴 Hummer、美团 MRN / Recce、京东 Taro-Native、拼多多 Lego、支付宝 Nebula / BirdNest、爱奇艺 Doric ……几乎每一家超级 App 都至少造过一套自己的动态化 DSL。 进入 2026 年 AI Coding 时代,动态化 DSL 的定位发生了根本性转变: 过去它服务于"业务迭代速度"——解决包大小限制、审核周期、多端复用问题。 现在它服务于"Agent 生成 UI"——LLM 更擅长生成 JSON / 结构化 DSL 而不是跨平台原生代码,DSL 成为 Generative UI / SDUI(Server-Driven UI)落地移动端的唯一高效载体。 本文从定义出发,讲透动态化 DSL 的历史演进、分类体系、核心渲染管线、关键原理(AST / 表达式引擎 / 布局 / 数据绑定 / 差分),再深入解剖 DinamicX、Tangram、LuaView、Lynx、Hummer、Recce 六大主流方案的工程实现,最后系统分析 AI Coding 时代的优劣势与决策矩阵。 ...

May 2, 2026