{"id":10021184,"date":"2026-01-10T13:43:49","date_gmt":"2026-01-10T05:43:49","guid":{"rendered":"https:\/\/itmax.cn\/?p=10021184"},"modified":"2026-01-10T13:43:49","modified_gmt":"2026-01-10T05:43:49","slug":"ripple%ef%bc%9a%e4%b8%80%e4%b8%aa%e7%8e%b0%e4%bb%a3%e7%9a%84%e5%93%8d%e5%ba%94%e5%bc%8f-ui-%e6%a1%86%e6%9e%b6","status":"publish","type":"post","link":"https:\/\/itmax.cn\/?p=10021184","title":{"rendered":"Ripple\uff1a\u4e00\u4e2a\u73b0\u4ee3\u7684\u54cd\u5e94\u5f0f UI \u6846\u67b6"},"content":{"rendered":"<blockquote><p>\u7528\u6700\u76f4\u89c2\u7684\u8bed\u6cd5\uff0c\u6784\u5efa\u6700\u9ad8\u6548\u7684 Web \u5e94\u7528<\/p><\/blockquote>\n<h2>AI \u65f6\u4ee3\uff0c\u66f4\u9700\u8981\u7cbe\u54c1\u6846\u67b6<\/h2>\n<p>2026 \u5e74\uff0cAI \u7f16\u7a0b\u5df2\u7ecf\u6210\u4e3a\u5e38\u6001\u3002Cursor\u3001Claude\u3001Copilot\u2026\u2026\u5f00\u53d1\u8005\u6bcf\u5929\u90fd\u5728\u7528 AI \u751f\u6210\u5927\u91cf\u4ee3\u7801\u3002<\/p>\n<p>\u4f46\u8fd9\u5e26\u6765\u4e86\u4e00\u4e2a\u65b0\u95ee\u9898\uff1a<strong>\u4ee3\u7801\u91cf\u7206\u70b8\uff0c\u8d28\u91cf\u5374\u5728\u4e0b\u964d\u3002<\/strong><\/p>\n<p>AI \u53ef\u4ee5\u5feb\u901f\u751f\u6210\u4ee3\u7801\uff0c\u4f46\u5b83\u751f\u6210\u7684\u5f80\u5f80\u662f&#8221;\u80fd\u8dd1\u5c31\u884c&#8221;\u7684\u4ee3\u7801\u2014\u2014\u5197\u4f59\u7684\u72b6\u6001\u7ba1\u7406\u3001\u4e0d\u5fc5\u8981\u7684\u91cd\u6e32\u67d3\u3001\u81c3\u80bf\u7684\u4f9d\u8d56\u3002\u5f53\u9879\u76ee\u89c4\u6a21\u589e\u957f\uff0c\u8fd9\u4e9b\u95ee\u9898\u4f1a\u88ab\u653e\u5927\u3002<\/p>\n<p><strong>AI \u65f6\u4ee3\u4e0d\u7f3a\u4ee3\u7801\uff0c\u7f3a\u7684\u662f\u7cbe\u54c1\u6846\u67b6<\/strong>\u2014\u2014\u80fd\u591f\u7ea6\u675f\u4ee3\u7801\u8d28\u91cf\u3001\u4fdd\u8bc1\u6027\u80fd\u3001\u51cf\u5c11\u51fa\u9519\u7684\u6846\u67b6\u3002<\/p>\n<h3>\u73b0\u6709\u6846\u67b6\u7684\u95ee\u9898<\/h3>\n<pre><code class=\"javascript\">\/\/ React: \u6837\u677f\u4ee3\u7801\u592a\u591a\nfunction Counter() {\n  const [count, setCount] = useState(0)\n  const increment = useCallback(() =&gt; {\n    setCount(prev =&gt; prev + 1)\n  }, [])\n  return &lt;button onClick={increment}&gt;{count}&lt;\/button&gt;\n}\n\n\/\/ Vue: \u9700\u8981\u8bb0\u4f4f .value\nconst count = ref(0)\ncount.value++  \/\/ \u5fd8\u8bb0 .value \u5c31\u51fa\u9519\n\n\/\/ \u8fd9\u4e9b&quot;\u4eea\u5f0f\u611f&quot;\u4ee3\u7801\uff0cAI \u53ef\u80fd\u5199\u5bf9\uff0c\u4e5f\u53ef\u80fd\u5199\u9519\n\/\/ \u66f4\u91cd\u8981\u7684\u662f\uff1a\u5b83\u4eec\u8ba9\u4ee3\u7801\u53d8\u5f97\u81c3\u80bf<\/code><\/pre>\n<h3>Ripple \u7684\u7b54\u6848\uff1a\u5c11\u5373\u662f\u591a<\/h3>\n<pre><code class=\"javascript\">component Counter() {\n  let count = track(0);\n  &lt;button onClick={() =&gt; @count++}&gt;{@count}&lt;\/button&gt;\n}<\/code><\/pre>\n<p><strong>4 \u884c\u4ee3\u7801\uff0c\u96f6\u6837\u677f\u3002<\/strong><\/p>\n<ul>\n<li>\u6ca1\u6709 <code>useState<\/code> \/ <code>ref<\/code> \/ <code>signal<\/code><\/li>\n<li>\u6ca1\u6709 <code>useCallback<\/code> \/ <code>useMemo<\/code><\/li>\n<li>\u6ca1\u6709 <code>.value<\/code> \/ <code>$:<\/code><\/li>\n<li>\u7f16\u8bd1\u5668\u81ea\u52a8\u4f18\u5316\uff0c\u8fd0\u884c\u65f6\u6781\u81f4\u7cbe\u7b80<\/li>\n<\/ul>\n<table>\n<thead>\n<tr>\n<th>\u6307\u6807<\/th>\n<th>React<\/th>\n<th>Vue<\/th>\n<th>Ripple<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>\u8ba1\u6570\u5668\u4ee3\u7801\u884c\u6570<\/td>\n<td>6-8 \u884c<\/td>\n<td>4-5 \u884c<\/td>\n<td><strong>3 \u884c<\/strong><\/td>\n<\/tr>\n<tr>\n<td>\u8fd0\u884c\u65f6\u5927\u5c0f<\/td>\n<td>~40KB<\/td>\n<td>~30KB<\/td>\n<td><strong>~5KB<\/strong><\/td>\n<\/tr>\n<tr>\n<td>\u66f4\u65b0\u7c92\u5ea6<\/td>\n<td>\u7ec4\u4ef6\u7ea7<\/td>\n<td>\u7ec4\u4ef6\u7ea7<\/td>\n<td><strong>\u8282\u70b9\u7ea7<\/strong><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h3>\u4e3a\u4ec0\u4e48\u8fd9\u5728 AI \u65f6\u4ee3\u66f4\u91cd\u8981\uff1f<\/h3>\n<ol>\n<li><strong>\u4ee3\u7801\u5ba1\u67e5\u6210\u672c<\/strong>\uff1aAI \u751f\u6210\u7684\u4ee3\u7801\u9700\u8981\u4eba\u5de5\u5ba1\u67e5\uff0c\u8d8a\u7b80\u6d01\u8d8a\u597d\u5ba1<\/li>\n<li><strong>\u9519\u8bef\u6982\u7387<\/strong>\uff1a\u8bed\u6cd5\u8d8a\u7b80\u5355\uff0cAI\uff08\u548c\u4eba\uff09\u51fa\u9519\u7684\u673a\u4f1a\u8d8a\u5c11<\/li>\n<li><strong>\u6027\u80fd\u515c\u5e95<\/strong>\uff1a\u5373\u4f7f AI \u4e0d\u8003\u8651\u6027\u80fd\uff0c\u7f16\u8bd1\u5668\u4f1a\u5e2e\u4f60\u4f18\u5316<\/li>\n<li><strong>\u53ef\u7ef4\u62a4\u6027<\/strong>\uff1a\u4e09\u4e2a\u6708\u540e\u56de\u770b\u4ee3\u7801\uff0c\u8fd8\u80fd\u4e00\u773c\u770b\u61c2<\/li>\n<\/ol>\n<p>Ripple \u7684\u8bbe\u8ba1\u54f2\u5b66\uff1a<strong>\u4ee3\u7801\u5e94\u8be5\u8bfb\u8d77\u6765\u50cf\u5b83\u505a\u7684\u4e8b\u60c5\u3002<\/strong><\/p>\n<hr>\n<h2>\u4e3a\u4ec0\u4e48\u9009\u62e9 Ripple\uff1f<\/h2>\n<p>Ripple \u8ffd\u6c42<strong>\u4e24\u5168\u5176\u7f8e<\/strong>\u2014\u2014\u65e2\u8981 React \u7684\u7ec4\u4ef6\u6a21\u578b\u548c JSX \u8868\u8fbe\u529b\uff0c\u53c8\u8981 Svelte \u7684\u7f16\u8bd1\u65f6\u4f18\u5316\u548c\u6781\u81f4\u6027\u80fd\u3002<\/p>\n<p>\u770b\u770b\u8fd9\u6bb5\u4ee3\u7801\uff1a<\/p>\n<pre><code class=\"javascript\">component Counter() {\n  let count = track(0);\n\n  &lt;button onClick={() =&gt; @count++}&gt;\n    {&quot;\u70b9\u51fb\u4e86 &quot;}{@count}{&quot; \u6b21&quot;}\n  &lt;\/button&gt;\n}<\/code><\/pre>\n<p>\u8fd9\u5c31\u662f Ripple\u3002\u6ca1\u6709 <code>useState<\/code>\uff0c\u6ca1\u6709 <code>$:<\/code>\uff0c\u6ca1\u6709 <code>.value<\/code>\u3002<code>track()<\/code> \u521b\u5efa\u72b6\u6001\uff0c<code>@<\/code> \u8bfb\u5199\u503c\uff0c\u7b80\u6d01\u76f4\u89c2\u3002<\/p>\n<h2>\u6838\u5fc3\u7406\u5ff5<\/h2>\n<h3>1. \u7f16\u8bd1\u5668\u4f18\u5148<\/h3>\n<p>Ripple \u4e0d\u662f\u4e00\u4e2a\u8fd0\u884c\u65f6\u6846\u67b6\uff0c\u800c\u662f\u4e00\u4e2a<strong>\u7f16\u8bd1\u5668<\/strong>\u3002\u4f60\u5199\u7684\u4ee3\u7801\u4f1a\u88ab\u8f6c\u6362\u6210\u9ad8\u6548\u7684 JavaScript\uff1a<\/p>\n<pre><code>\u4f60\u5199\u7684\u4ee3\u7801                         \u7f16\u8bd1\u540e\u7684\u4ee3\u7801\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500                     \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\nlet count = track(0)    \u2192        var count = _$_.tracked(0)\n{@count}                \u2192        _$_.get(count)\n@count++                \u2192        _$_.update(count)<\/code><\/pre>\n<p>\u8fd9\u610f\u5473\u7740\uff1a<\/p>\n<ul>\n<li><strong>\u96f6\u8fd0\u884c\u65f6\u5f00\u9500<\/strong>\uff1a\u54cd\u5e94\u5f0f\u8ffd\u8e2a\u5728\u7f16\u8bd1\u65f6\u5b8c\u6210<\/li>\n<li><strong>\u66f4\u5c0f\u7684\u5305\u4f53\u79ef<\/strong>\uff1a\u6ca1\u6709\u865a\u62df DOM diff \u7b97\u6cd5<\/li>\n<li><strong>\u66f4\u5feb\u7684\u66f4\u65b0<\/strong>\uff1a\u76f4\u63a5\u64cd\u4f5c\u9700\u8981\u66f4\u65b0\u7684 DOM \u8282\u70b9<\/li>\n<\/ul>\n<h3>2. \u7ec4\u4ef6\u5373\u51fd\u6570<\/h3>\n<p>\u5728 Ripple \u4e2d\uff0c\u7ec4\u4ef6\u5c31\u662f\u5e26\u6709 <code>component<\/code> \u5173\u952e\u5b57\u7684\u51fd\u6570\uff1a<\/p>\n<pre><code class=\"javascript\">component Greeting({ name = &quot;World&quot; }) {\n  &lt;h1&gt;{&quot;Hello, &quot;}{name}{&quot;!&quot;}&lt;\/h1&gt;\n}\n\n\/\/ \u4f7f\u7528\n&lt;Greeting name=&quot;Ripple&quot; \/&gt;<\/code><\/pre>\n<h3>3. \u54cd\u5e94\u5f0f\u72b6\u6001\uff1a<code>track()<\/code> \u548c <code>@<\/code> \u8bed\u6cd5<\/h3>\n<p>\u7528 <code>track()<\/code> \u521b\u5efa\u54cd\u5e94\u5f0f\u53d8\u91cf\uff0c\u7528 <code>@<\/code> \u8bfb\u5199\u503c\uff1a<\/p>\n<pre><code class=\"javascript\">component Form() {\n  let name = track(&quot;&quot;);\n  let email = track(&quot;&quot;);\n\n  &lt;form&gt;\n    &lt;input value={@name} onInput={(e) =&gt; @name = e.target.value} \/&gt;\n    &lt;input value={@email} onInput={(e) =&gt; @email = e.target.value} \/&gt;\n    &lt;p&gt;{&quot;\u4f60\u597d\uff0c&quot;}{@name}{&quot;\uff01\u6211\u4eec\u4f1a\u53d1\u90ae\u4ef6\u5230 &quot;}{@email}&lt;\/p&gt;\n  &lt;\/form&gt;\n}<\/code><\/pre>\n<h3>4. \u54cd\u5e94\u5f0f\u96c6\u5408\uff1a<code>#[]<\/code> \u548c <code>#{}<\/code><\/h3>\n<p>\u6570\u7ec4\u548c\u5bf9\u8c61\u4e5f\u53ef\u4ee5\u662f\u54cd\u5e94\u5f0f\u7684\uff1a<\/p>\n<pre><code class=\"javascript\">const items = #[];                          \/\/ \u54cd\u5e94\u5f0f\u6570\u7ec4\nconst user = #{ name: &quot;Tom&quot; };              \/\/ \u54cd\u5e94\u5f0f\u5bf9\u8c61\nconst tags = new TrackedSet([&quot;a&quot;, &quot;b&quot;]);    \/\/ \u54cd\u5e94\u5f0f Set\nconst cache = new TrackedMap([[&quot;k&quot;, &quot;v&quot;]]); \/\/ \u54cd\u5e94\u5f0f Map<\/code><\/pre>\n<p>\u5bf9\u8fd9\u4e9b\u96c6\u5408\u7684\u4efb\u4f55\u4fee\u6539\u90fd\u4f1a\u81ea\u52a8\u89e6\u53d1 UI \u66f4\u65b0\uff1a<\/p>\n<pre><code class=\"javascript\">items.push(&quot;new item&quot;);   \/\/ UI \u81ea\u52a8\u66f4\u65b0\nuser.name = &quot;Jerry&quot;;      \/\/ UI \u81ea\u52a8\u66f4\u65b0<\/code><\/pre>\n<hr>\n<h2>\u5b9e\u6218\uff1a\u6784\u5efa\u4e00\u4e2a Todo \u5e94\u7528<\/h2>\n<p>\u8ba9\u6211\u4eec\u7528 Ripple \u6784\u5efa\u4e00\u4e2a\u5b8c\u6574\u7684 Todo \u5e94\u7528\uff0c\u4f53\u9a8c\u6846\u67b6\u7684\u6838\u5fc3\u7279\u6027\u3002<\/p>\n<h3>\u5b8c\u6574\u4ee3\u7801<\/h3>\n<pre><code class=\"javascript\">import { track } from 'ripple';\n\ncomponent TodoInput({ onAdd }) {\n  let value = track(&quot;&quot;);\n\n  function handleKeyDown(e) {\n    if (e.key === &quot;Enter&quot; &amp;&amp; @value.trim()) {\n      onAdd(@value.trim());\n      @value = &quot;&quot;;\n    }\n  }\n\n  &lt;div class=&quot;input-section&quot;&gt;\n    &lt;input\n      type=&quot;text&quot;\n      placeholder=&quot;Add a new todo...&quot;\n      value={@value}\n      onInput={(e) =&gt; @value = e.target.value}\n      onKeyDown={handleKeyDown}\n    \/&gt;\n    &lt;button onClick={() =&gt; { if (@value.trim()) { onAdd(@value.trim()); @value = &quot;&quot;; } }}&gt;{&quot;Add&quot;}&lt;\/button&gt;\n  &lt;\/div&gt;\n}\n\ncomponent TodoItem({ todo, onToggle, onDelete }) {\n  &lt;li&gt;\n    &lt;input type=&quot;checkbox&quot; checked={todo.completed} onChange={onToggle} \/&gt;\n    &lt;span class={todo.completed ? &quot;done&quot; : &quot;&quot;}&gt;{todo.text}&lt;\/span&gt;\n    &lt;button onClick={onDelete}&gt;{&quot;\u00d7&quot;}&lt;\/button&gt;\n  &lt;\/li&gt;\n}\n\nexport component App() {\n  const todos = #[];\n\n  function addTodo(text) {\n    todos.push(#{ id: Date.now(), text, completed: false });\n  }\n\n  function toggleTodo(todo) {\n    todo.completed = !todo.completed;\n  }\n\n  function deleteTodo(id) {\n    const index = todos.findIndex(t =&gt; t.id === id);\n    if (index &gt; -1) todos.splice(index, 1);\n  }\n\n  const activeCount = () =&gt; todos.filter(t =&gt; !t.completed).length;\n\n  &lt;div class=&quot;app&quot;&gt;\n    &lt;h1&gt;{&quot;Todo App&quot;}&lt;\/h1&gt;\n\n    &lt;TodoInput onAdd={addTodo} \/&gt;\n\n    &lt;ul&gt;\n      for (const todo of todos) {\n        &lt;TodoItem\n          todo={todo}\n          onToggle={() =&gt; toggleTodo(todo)}\n          onDelete={() =&gt; deleteTodo(todo.id)}\n        \/&gt;\n      }\n    &lt;\/ul&gt;\n\n    &lt;p&gt;{todos.length}{&quot; total, &quot;}{activeCount()}{&quot; remaining&quot;}&lt;\/p&gt;\n  &lt;\/div&gt;\n\n  &lt;style&gt;\n    .app { max-width: 400px; margin: 40px auto; font-family: system-ui; }\n    h1 { color: #e91e63; }\n    .input-section { display: flex; gap: 8px; margin-bottom: 16px; }\n    .input-section input { flex: 1; padding: 8px; }\n    ul { list-style: none; padding: 0; }\n    li { display: flex; gap: 8px; align-items: center; padding: 8px 0; }\n    li span { flex: 1; }\n    li span.done { text-decoration: line-through; color: #888; }\n    p { color: #666; font-size: 14px; }\n  &lt;\/style&gt;\n}<\/code><\/pre>\n<h3>\u4ee3\u7801\u89e3\u6790<\/h3>\n<h4>1. \u54cd\u5e94\u5f0f\u6570\u7ec4 <code>#[]<\/code><\/h4>\n<pre><code class=\"javascript\">const todos = #[];<\/code><\/pre>\n<p><code>#[]<\/code> \u521b\u5efa\u4e00\u4e2a\u54cd\u5e94\u5f0f\u6570\u7ec4\u3002\u5f53\u4f60\u8c03\u7528 <code>push<\/code>\u3001<code>splice<\/code>\u3001<code>filter<\/code> \u7b49\u65b9\u6cd5\u65f6\uff0cRipple \u4f1a\u81ea\u52a8\u8ffd\u8e2a\u53d8\u5316\u5e76\u66f4\u65b0 UI\u3002<\/p>\n<h4>2. \u54cd\u5e94\u5f0f\u5bf9\u8c61 <code>#{}<\/code><\/h4>\n<pre><code class=\"javascript\">todos.push(#{ id: Date.now(), text, completed: false });<\/code><\/pre>\n<p>\u6bcf\u4e2a todo \u9879\u4e5f\u662f\u54cd\u5e94\u5f0f\u5bf9\u8c61\uff0c\u8fd9\u6837 <code>todo.completed = !todo.completed<\/code> \u5c31\u80fd\u89e6\u53d1\u66f4\u65b0\u3002<\/p>\n<h4>3. \u63a7\u5236\u6d41\uff1a\u5185\u8054 <code>for<\/code> \u548c <code>if<\/code><\/h4>\n<pre><code class=\"javascript\">for (const todo of todos) {\n  &lt;TodoItem todo={todo} ... \/&gt;\n}\n\nif (todos.some(t =&gt; t.completed)) {\n  &lt;button&gt;{&quot;\u6e05\u9664\u5df2\u5b8c\u6210&quot;}&lt;\/button&gt;\n}<\/code><\/pre>\n<p>Ripple \u7684\u63a7\u5236\u6d41\u76f4\u63a5\u5199\u5728 JSX \u4e2d\uff0c\u4e0d\u9700\u8981 <code>map<\/code> \u6216\u4e09\u5143\u8868\u8fbe\u5f0f\u3002\u7f16\u8bd1\u5668\u4f1a\u5c06\u5176\u8f6c\u6362\u4e3a\u9ad8\u6548\u7684 block \u7ed3\u6784\u3002<\/p>\n<h4>4. \u4f5c\u7528\u57df\u6837\u5f0f<\/h4>\n<pre><code class=\"javascript\">&lt;style&gt;\n  .todo-item { ... }\n&lt;\/style&gt;<\/code><\/pre>\n<p>\u7ec4\u4ef6\u5185\u7684 <code>&lt;style&gt;<\/code> \u6807\u7b7e\u4f1a\u88ab\u81ea\u52a8\u6dfb\u52a0\u4f5c\u7528\u57df\u54c8\u5e0c\uff0c\u4e0d\u4f1a\u6c61\u67d3\u5168\u5c40\u6837\u5f0f\u3002<\/p>\n<hr>\n<h2>\u7f16\u8bd1\u4ea7\u7269\u4e00\u89c8<\/h2>\n<p>\u597d\u5947 Ripple \u7f16\u8bd1\u5668\u505a\u4e86\u4ec0\u4e48\uff1f\u6765\u770b\u770b <code>@count++<\/code> \u8fd9\u884c\u4ee3\u7801\u7684\u65c5\u7a0b\uff1a<\/p>\n<pre><code>\u6e90\u7801                     \u7f16\u8bd1\u9636\u6bb5               \u8fd0\u884c\u65f6\n\u2500\u2500\u2500\u2500                     \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500               \u2500\u2500\u2500\u2500\u2500\u2500\n\nlet count = track(0)  \u2192  \u89e3\u6790\u4e3a AST     \u2192    var count = _$_.tracked(0)\n                         (TrackedExpression)\n\n@count++              \u2192  \u5206\u6790\u7ed1\u5b9a\u7c7b\u578b    \u2192    _$_.update(count)\n                         (kind: 'tracked')\n\n{@count}              \u2192  \u8f6c\u6362\u4e3a\u6e32\u67d3\u51fd\u6570  \u2192    _$_.render(() =&gt; {\n                                               _$_.set_text(anchor, _$_.get(count))\n                                             })<\/code><\/pre>\n<p><strong>\u4e09\u9636\u6bb5\u7f16\u8bd1\u6d41\u7a0b\uff1a<\/strong><\/p>\n<ol>\n<li><strong>\u89e3\u6790 (Parse)<\/strong>\uff1a\u5c06\u6e90\u7801\u8f6c\u4e3a AST\uff0c\u8bc6\u522b <code>@<\/code>\u3001<code>#[]<\/code>\u3001<code>component<\/code> \u7b49\u7279\u6b8a\u8bed\u6cd5<\/li>\n<li><strong>\u5206\u6790 (Analyze)<\/strong>\uff1a\u6784\u5efa\u4f5c\u7528\u57df\u3001\u6807\u8bb0\u53d8\u91cf\u7c7b\u578b\u3001\u88c1\u526a\u672a\u4f7f\u7528\u7684 CSS<\/li>\n<li><strong>\u8f6c\u6362 (Transform)<\/strong>\uff1a\u751f\u6210\u5ba2\u6237\u7aef\/\u670d\u52a1\u7aef JavaScript \u4ee3\u7801<\/li>\n<\/ol>\n<hr>\n<h2>\u4e0e\u5176\u4ed6\u6846\u67b6\u5bf9\u6bd4<\/h2>\n<table>\n<thead>\n<tr>\n<th>\u7279\u6027<\/th>\n<th>Ripple<\/th>\n<th>React<\/th>\n<th>Vue 3<\/th>\n<th>Svelte<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>\u54cd\u5e94\u5f0f\u8bed\u6cd5<\/td>\n<td><code>track()<\/code> + <code>@<\/code><\/td>\n<td><code>useState<\/code><\/td>\n<td><code>ref().value<\/code><\/td>\n<td><code>$:<\/code><\/td>\n<\/tr>\n<tr>\n<td>\u865a\u62df DOM<\/td>\n<td>\u65e0<\/td>\n<td>\u6709<\/td>\n<td>\u6709<\/td>\n<td>\u65e0<\/td>\n<\/tr>\n<tr>\n<td>\u7f16\u8bd1\u65f6\u4f18\u5316<\/td>\n<td>\u662f<\/td>\n<td>\u5426<\/td>\n<td>\u90e8\u5206<\/td>\n<td>\u662f<\/td>\n<\/tr>\n<tr>\n<td>\u5305\u4f53\u79ef<\/td>\n<td>~5KB<\/td>\n<td>~40KB<\/td>\n<td>~30KB<\/td>\n<td>~2KB<\/td>\n<\/tr>\n<tr>\n<td>\u5b66\u4e60\u66f2\u7ebf<\/td>\n<td>\u4f4e<\/td>\n<td>\u4e2d<\/td>\n<td>\u4e2d<\/td>\n<td>\u4f4e<\/td>\n<\/tr>\n<tr>\n<td>\u63a7\u5236\u6d41<\/td>\n<td>\u5185\u8054\u8bed\u6cd5<\/td>\n<td>map\/\u4e09\u5143<\/td>\n<td>v-if\/v-for<\/td>\n<td>{#if}\/{#each}<\/td>\n<\/tr>\n<tr>\n<td>\u6837\u677f\u4ee3\u7801<\/td>\n<td><strong>\u6781\u5c11<\/strong><\/td>\n<td>\u591a<\/td>\n<td>\u4e2d<\/td>\n<td>\u5c11<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<hr>\n<h2>\u7f16\u8bd1\u5668\uff1a\u8d28\u91cf\u7684\u5b88\u62a4\u8005<\/h2>\n<p>Ripple \u7684\u7f16\u8bd1\u5668\u4e0d\u53ea\u662f&#8221;\u7ffb\u8bd1&#8221;\u4ee3\u7801\uff0c\u5b83\u662f\u4ee3\u7801\u8d28\u91cf\u7684\u5b88\u62a4\u8005\uff1a<\/p>\n<h3>1. \u81ea\u52a8\u4f9d\u8d56\u8ffd\u8e2a<\/h3>\n<pre><code class=\"javascript\">\/\/ \u4f60\u53ea\u9700\u8981\u5199\u4e1a\u52a1\u903b\u8f91\nconst fullName = () =&gt; `${@firstName} ${@lastName}`\n\n\/\/ \u7f16\u8bd1\u5668\u81ea\u52a8\u5206\u6790\u4f9d\u8d56\uff0c\u751f\u6210\u4f18\u5316\u4ee3\u7801\uff1a\n\/\/ _$_.render(() =&gt; set_text(anchor, `${get(firstName)} ${get(lastName)}`))<\/code><\/pre>\n<p>\u4e0d\u9700\u8981 <code>useMemo([dep1, dep2])<\/code>\uff0c\u7f16\u8bd1\u5668\u6bd4\u4f60\u66f4\u6e05\u695a\u4f9d\u8d56\u5173\u7cfb\u3002<\/p>\n<h3>2. CSS \u6b7b\u4ee3\u7801\u6d88\u9664<\/h3>\n<pre><code class=\"javascript\">component Button() {\n  &lt;button class=&quot;primary&quot;&gt;{&quot;Click&quot;}&lt;\/button&gt;\n\n  &lt;style&gt;\n    .primary { background: blue; }\n    .secondary { background: gray; }  \/* \u7f16\u8bd1\u5668\u81ea\u52a8\u79fb\u9664 *\/\n    .danger { background: red; }      \/* \u7f16\u8bd1\u5668\u81ea\u52a8\u79fb\u9664 *\/\n  &lt;\/style&gt;\n}<\/code><\/pre>\n<p>\u4e0d\u7528\u62c5\u5fc3 CSS \u8d8a\u5199\u8d8a\u591a\uff0c\u7f16\u8bd1\u5668\u53ea\u4fdd\u7559\u771f\u6b63\u7528\u5230\u7684\u6837\u5f0f\u3002<\/p>\n<h3>3. \u7ec6\u7c92\u5ea6\u66f4\u65b0<\/h3>\n<pre><code class=\"javascript\">component Profile() {\n  const user = #{ name: &quot;Tom&quot;, bio: &quot;Developer&quot; };\n\n  &lt;div&gt;\n    &lt;h1&gt;{user.name}&lt;\/h1&gt;      {\/* \u53ea\u5728 name \u53d8\u5316\u65f6\u66f4\u65b0 *\/}\n    &lt;p&gt;{user.bio}&lt;\/p&gt;         {\/* \u53ea\u5728 bio \u53d8\u5316\u65f6\u66f4\u65b0 *\/}\n  &lt;\/div&gt;\n}<\/code><\/pre>\n<p>\u7f16\u8bd1\u5668\u5206\u6790\u6bcf\u4e2a\u8868\u8fbe\u5f0f\u7684\u4f9d\u8d56\uff0c\u751f\u6210\u6700\u7cbe\u786e\u7684\u66f4\u65b0\u903b\u8f91\u3002<\/p>\n<hr>\n<h2>\u8ba9 AI \u66f4\u61c2 Ripple<\/h2>\n<p>Ripple \u63d0\u4f9b\u4e86 <a href=\"https:\/\/link.segmentfault.com\/?enc=6DDX66pUys3%2FPeVUIVF5Vw%3D%3D.nQ1veZQ9hMpTCzxnazVvD%2BphYGMRKjdBgNk5HnIk4e%2BRf1wNsgsMMgFFYI5z1o%2B%2F\" rel=\"nofollow noopener noreferrer\" target=\"_blank\">llms.txt<\/a>\uff0c\u8fd9\u662f\u4e00\u4efd\u4e13\u4e3a AI \u52a9\u624b\u8bbe\u8ba1\u7684\u6846\u67b6\u8bf4\u660e\u6587\u6863\u3002<\/p>\n<p>\u5f53\u4f60\u4f7f\u7528 Claude\u3001ChatGPT \u6216\u5176\u4ed6 AI \u52a9\u624b\u65f6\uff0c\u53ef\u4ee5\u8ba9\u5b83\u5148\u9605\u8bfb\u8fd9\u4efd\u6587\u6863\uff1a<\/p>\n<pre><code>\u8bf7\u5148\u9605\u8bfb https:\/\/www.ripplejs.com\/llms.txt\uff0c\u7136\u540e\u5e2e\u6211\u7528 Ripple \u6846\u67b6\u5b9e\u73b0\u4e00\u4e2a [\u529f\u80fd\u63cf\u8ff0]<\/code><\/pre>\n<p>llms.txt \u5305\u542b\uff1a<\/p>\n<ul>\n<li>Ripple \u6838\u5fc3\u8bed\u6cd5\u901f\u67e5<\/li>\n<li>\u5e38\u89c1\u6a21\u5f0f\u548c\u6700\u4f73\u5b9e\u8df5<\/li>\n<li>\u6613\u9519\u70b9\u548c\u6b63\u786e\u5199\u6cd5<\/li>\n<li>\u5b8c\u6574\u793a\u4f8b\u4ee3\u7801<\/li>\n<\/ul>\n<p>\u8fd9\u786e\u4fdd AI \u751f\u6210\u7684\u4ee3\u7801\u7b26\u5408 Ripple \u7684\u8bbe\u8ba1\u7406\u5ff5\uff0c\u800c\u4e0d\u662f\u7528 React \u7684\u601d\u7ef4\u5199 Ripple\u3002<\/p>\n<hr>\n<h2>\u5feb\u901f\u5f00\u59cb<\/h2>\n<pre><code class=\"bash\"># \u521b\u5efa\u65b0\u9879\u76ee\nnpx create-ripple-app my-app\ncd my-app\n\n# \u542f\u52a8\u5f00\u53d1\u670d\u52a1\u5668\nnpm run dev<\/code><\/pre>\n<p>\u7136\u540e\u6253\u5f00 <code>src\/App.ripple<\/code>\uff0c\u5f00\u59cb\u7f16\u5199\u4f60\u7684\u7b2c\u4e00\u4e2a Ripple \u7ec4\u4ef6\uff01<\/p>\n<hr>\n<h2>\u5199\u5728\u6700\u540e<\/h2>\n<p>AI \u8ba9\u5199\u4ee3\u7801\u53d8\u5f97\u66f4\u5feb\u4e86\uff0c\u4f46&#8221;\u66f4\u5feb&#8221;\u4e0d\u7b49\u4e8e&#8221;\u66f4\u597d&#8221;\u3002<\/p>\n<p>\u5f53\u4ee3\u7801\u751f\u6210\u7684\u901f\u5ea6\u8d85\u8fc7\u7406\u89e3\u7684\u901f\u5ea6\uff0c\u6211\u4eec\u66f4\u9700\u8981\uff1a<\/p>\n<ul>\n<li><strong>\u7cbe\u7b80\u7684\u8bed\u6cd5<\/strong> \u2014 \u8ba9\u4ee3\u7801\u91cf\u56de\u5f52\u7406\u6027<\/li>\n<li><strong>\u7f16\u8bd1\u65f6\u4f18\u5316<\/strong> \u2014 \u8ba9\u6027\u80fd\u6709\u4fdd\u969c<\/li>\n<li><strong>\u76f4\u89c2\u7684\u5fc3\u667a\u6a21\u578b<\/strong> \u2014 \u8ba9\u7ef4\u62a4\u4e0d\u518d\u75db\u82e6<\/li>\n<\/ul>\n<p>Ripple \u4e0d\u662f\u4e3a\u4e86\u8ffd\u9010\u65b0\u6982\u5ff5\u800c\u751f\uff0c\u800c\u662f\u5bf9&#8221;\u524d\u7aef\u5f00\u53d1\u5e94\u8be5\u662f\u4ec0\u4e48\u6837&#8221;\u7684\u4e00\u6b21\u56de\u7b54\u3002<\/p>\n<p><strong>\u5c11\u5199\u4ee3\u7801\uff0c\u5199\u597d\u4ee3\u7801\u3002<\/strong><\/p>\n<hr>\n<p><em>Ripple \u2014 \u8ba9\u54cd\u5e94\u5f0f\u56de\u5f52\u7b80\u5355<\/em><\/p>\n<p><a href=\"https:\/\/link.segmentfault.com\/?enc=EBi%2FsCdlFal3c%2FdBt5pT2w%3D%3D.CMHqtyZ56bX2jJ8GYB81L8q2WJEiPJ6uAZ8qtEYt1XBs2UgfjKMdvr6ecW1wOtD9\" rel=\"nofollow noopener noreferrer\" target=\"_blank\">GitHub<\/a> \u00b7 <a href=\"https:\/\/link.segmentfault.com\/?enc=2RSeS8RSDjSay5cFvgixAg%3D%3D.kKgTGrie%2BkV4ADpIlpenv9kuY8xVhayaYSsaQ19sEU8%3D\" rel=\"nofollow noopener noreferrer\" target=\"_blank\">\u6587\u6863<\/a> \u00b7 <a href=\"https:\/\/link.segmentfault.com\/?enc=ORn%2FhBCz3CnQkGeNI%2BJxWg%3D%3D.GLXxsqicrThDvZV2J0n7jVFJhJ2qX2SfNocxQ1jVUu%2BePpioUF6d3sSOhZj4axDh\" rel=\"nofollow noopener noreferrer\" target=\"_blank\">llms.txt<\/a><\/p>\n<p><a href=\"https:\/\/segmentfault.com\/a\/1190000047533709\">https:\/\/segmentfault.com\/a\/1190000047533709<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u7528\u6700\u76f4\u89c2\u7684\u8bed\u6cd5\uff0c\u6784\u5efa\u6700\u9ad8\u6548\u7684 Web \u5e94\u7528 AI \u65f6\u4ee3\uff0c\u66f4\u9700\u8981\u7cbe\u54c1\u6846\u67b6 2026 \u5e74\uff0cAI \u7f16\u7a0b\u5df2\u7ecf\u6210\u4e3a\u5e38\u6001\u3002 [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[4],"tags":[],"class_list":["post-10021184","post","type-post","status-publish","format-standard","hentry","category-share"],"jetpack_sharing_enabled":true,"jetpack_featured_media_url":"","_links":{"self":[{"href":"https:\/\/itmax.cn\/index.php?rest_route=\/wp\/v2\/posts\/10021184","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/itmax.cn\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/itmax.cn\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/itmax.cn\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/itmax.cn\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=10021184"}],"version-history":[{"count":0,"href":"https:\/\/itmax.cn\/index.php?rest_route=\/wp\/v2\/posts\/10021184\/revisions"}],"wp:attachment":[{"href":"https:\/\/itmax.cn\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=10021184"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/itmax.cn\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=10021184"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/itmax.cn\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=10021184"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}