{"id":10021154,"date":"2025-12-30T02:08:32","date_gmt":"2025-12-29T18:08:32","guid":{"rendered":"https:\/\/itmax.cn\/?p=10021154"},"modified":"2025-12-30T02:08:32","modified_gmt":"2025-12-29T18:08:32","slug":"grit%ef%bc%9a%e4%bb%a3%e7%a0%81%e9%87%8d%e6%9e%84%e5%88%a9%e5%99%a8","status":"publish","type":"post","link":"https:\/\/itmax.cn\/?p=10021154","title":{"rendered":"Grit\uff1a\u4ee3\u7801\u91cd\u6784\u5229\u5668"},"content":{"rendered":"<blockquote><p>\u9762\u5bf9\u9700\u8981\u4fee\u6539\u6570\u767e\u4e2a\u6587\u4ef6\u7684\u4ee3\u7801\u8fc1\u79fb\uff0c\u4f60\u8fd8\u5728\u624b\u52a8\u4e00\u4e2a\u4e2a\u6539\u5417\uff1f\u4eca\u5929\u4ecb\u7ecd\u4e00\u6b3e\u80fd\u8ba9\u4ee3\u7801\u6279\u91cf\u91cd\u6784\u50cf\u67e5\u627e\u66ff\u6362\u4e00\u6837\u7b80\u5355\u7684\u5de5\u5177 \u2014\u2014 Grit\u3002<\/p><\/blockquote>\n<h2>\u4e3a\u4ec0\u4e48\u9700\u8981 Grit<\/h2>\n<p>\u4f5c\u4e3a\u5f00\u53d1\u8005\uff0c\u6211\u4eec\u7ecf\u5e38\u9047\u5230\u8fd9\u6837\u7684\u573a\u666f\uff1a<\/p>\n<ul>\n<li>\u56e2\u961f\u51b3\u5b9a\u7edf\u4e00\u4f7f\u7528 <code>lodash-es<\/code> \u66ff\u4ee3 <code>lodash<\/code>\uff0c\u9700\u8981\u4fee\u6539\u51e0\u767e\u4e2a import \u8bed\u53e5<\/li>\n<li>\u9879\u76ee\u8981\u4ece React \u7c7b\u7ec4\u4ef6\u8fc1\u79fb\u5230 Hooks\uff0c\u6d89\u53ca\u4e0a\u5343\u4e2a\u7ec4\u4ef6<\/li>\n<li>\u67d0\u4e2a\u5e9f\u5f03\u7684 API \u9700\u8981\u5168\u9762\u66ff\u6362\uff0c\u4f46\u8c03\u7528\u4f4d\u7f6e\u6563\u843d\u5728\u4ee3\u7801\u5e93\u5404\u5904<\/li>\n<\/ul>\n<p>\u4f20\u7edf\u7684\u89e3\u51b3\u65b9\u6848\u5404\u6709\u75db\u70b9\uff1a<\/p>\n<table>\n<thead>\n<tr>\n<th>\u65b9\u6848<\/th>\n<th>\u95ee\u9898<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>\u624b\u52a8\u4fee\u6539<\/td>\n<td>\u8017\u65f6\u957f\u3001\u6613\u9057\u6f0f\u3001\u5bb9\u6613\u51fa\u9519<\/td>\n<\/tr>\n<tr>\n<td>\u6b63\u5219\u66ff\u6362<\/td>\n<td>\u4e0d\u7406\u89e3\u4ee3\u7801\u7ed3\u6784\uff0c\u5bb9\u6613\u8bef\u4f24<\/td>\n<\/tr>\n<tr>\n<td>jscodeshift<\/td>\n<td>\u4ec5\u652f\u6301 JS\/TS\uff0c\u9700\u61c2 AST\uff0c\u7f16\u5199\u590d\u6742<\/td>\n<\/tr>\n<tr>\n<td>find + sed<\/td>\n<td>\u8106\u5f31\uff0c\u96be\u4ee5\u5904\u7406\u590d\u6742\u573a\u666f<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p><strong>Grit<\/strong> \u5c31\u662f\u4e3a\u4e86\u89e3\u51b3\u8fd9\u4e9b\u95ee\u9898\u800c\u751f\u7684 \u2014\u2014 \u5b83\u7528\u58f0\u660e\u5f0f\u7684\u8bed\u6cd5\uff0c\u652f\u6301\u591a\u79cd\u8bed\u8a00\uff0c\u8ba9\u4efb\u4f55\u4eba\u90fd\u80fd\u5199\u51fa\u5b89\u5168\u7684\u4ee3\u7801\u8f6c\u6362\u89c4\u5219\u3002<\/p>\n<hr>\n<h2>\u5feb\u901f\u5f00\u59cb<\/h2>\n<h3>\u5b89\u88c5<\/h3>\n<pre><code class=\"bash\"># \u65b9\u5f0f\u4e00\uff1a\u5b98\u65b9\u5b89\u88c5\u811a\u672c\ncurl -fsSL https:\/\/docs.grit.io\/install | bash\n\n# \u65b9\u5f0f\u4e8c\uff1anpm \u5b89\u88c5\nnpm install -g @getgrit\/cli<\/code><\/pre>\n<h3>\u9a8c\u8bc1\u5b89\u88c5<\/h3>\n<pre><code class=\"bash\"># \u68c0\u67e5\u7248\u672c\ngrit version\n\n# \u8bca\u65ad\u73af\u5883\ngrit doctor<\/code><\/pre>\n<h3>\u7b2c\u4e00\u4e2a\u8f6c\u6362<\/h3>\n<p>\u5047\u8bbe\u6211\u4eec\u8981\u628a\u6240\u6709\u7684 <code>console.log<\/code> \u8c03\u7528\u5220\u9664\uff1a<\/p>\n<pre><code class=\"bash\"># \u65b9\u5f0f\u4e00\uff1a\u4f7f\u7528\u6807\u51c6\u5e93 pattern\uff08\u63a8\u8350\uff09\ngrit apply no_console_log src\/\n\n# \u65b9\u5f0f\u4e8c\uff1a\u4f7f\u7528\u5185\u8054 pattern\ngrit apply '`console.log($_)`' src\/\n\n# \u5148\u9884\u89c8\u4f1a\u6539\u4ec0\u4e48\uff08dry-run\uff09\ngrit apply --dry-run no_console_log src\/\n\n# \u67e5\u770b\u67d0\u4e2a pattern \u7684\u8be6\u7ec6\u4fe1\u606f\ngrit patterns describe no_console_log<\/code><\/pre>\n<hr>\n<h2>\u6838\u5fc3\u547d\u4ee4<\/h2>\n<h3>grit apply &#8211; \u5e94\u7528\u8f6c\u6362<\/h3>\n<p><strong>\u8bed\u6cd5<\/strong>: <code>grit apply [OPTIONS] &lt;PATTERN&gt; [PATHS]...<\/code><\/p>\n<p><strong>Pattern \u53c2\u6570\u5f62\u5f0f<\/strong>\uff1a<\/p>\n<ul>\n<li>\u6807\u51c6\u5e93 pattern: <code>no_console_log<\/code><\/li>\n<li>\u5185\u8054\u6a21\u5f0f: <code>'<\/code>console.log($_)<code>'<\/code>\uff08\u7528\u5355\u5f15\u53f7\u5305\u88f9\u53cd\u5f15\u53f7\u5185\u7684 pattern\uff09<\/li>\n<li>Pattern \u6587\u4ef6: <code>.\/patterns\/my_pattern.grit<\/code><\/li>\n<\/ul>\n<p><strong>\u5e38\u7528\u9009\u9879<\/strong>\uff1a<\/p>\n<pre><code class=\"bash\"># \u9884\u89c8\u6a21\u5f0f\uff08\u4e0d\u5b9e\u9645\u4fee\u6539\u6587\u4ef6\uff09\ngrit apply --dry-run no_console_log file.js\n\n# \u6307\u5b9a\u8bed\u8a00\ngrit apply --language python print_to_log file.py\n\n# \u9650\u5236\u4fee\u6539\u6570\u91cf\ngrit apply --limit 10 no_console_log src\/\n\n# \u7d27\u51d1\u8f93\u51fa\ngrit apply --output compact no_console_log src\/\n\n# \u4ea4\u4e92\u5f0f\u9009\u62e9\uff08\u9010\u4e2a\u786e\u8ba4\uff09\ngrit apply --interactive no_console_log src\/\n\n# JSONL \u683c\u5f0f\u8f93\u51fa\ngrit apply --jsonl no_console_log src\/<\/code><\/pre>\n<h3>grit list &#8211; \u5217\u51fa\u53ef\u7528 Patterns<\/h3>\n<pre><code class=\"bash\"># \u5217\u51fa\u6240\u6709 patterns\ngrit list\n\n# \u4ec5\u5217\u51fa JavaScript\/TypeScript patterns\ngrit list --language js\n\n# \u4ec5\u5217\u51fa Python patterns\ngrit list --language python\n\n# \u4ec5\u5217\u51fa\u672c\u5730 patterns\ngrit list --source local<\/code><\/pre>\n<h3>grit check &#8211; \u68c0\u67e5\u4ee3\u7801<\/h3>\n<pre><code class=\"bash\"># \u68c0\u67e5\u5f53\u524d\u76ee\u5f55\ngrit check\n\n# \u81ea\u52a8\u4fee\u590d\ngrit check --fix\n\n# \u8be6\u7ec6\u8f93\u51fa\ngrit check --verbose<\/code><\/pre>\n<h3>\u5176\u4ed6\u6709\u7528\u547d\u4ee4<\/h3>\n<pre><code class=\"bash\"># \u63cf\u8ff0\u67d0\u4e2a pattern\ngrit patterns describe no_console_log\n\n# \u5217\u51fa patterns\ngrit patterns list\n\n# \u8bca\u65ad\u73af\u5883\ngrit doctor<\/code><\/pre>\n<hr>\n<h2>\u6838\u5fc3\u8bed\u6cd5<\/h2>\n<h3>\u4ee3\u7801\u7247\u6bb5\u6a21\u5f0f<\/h3>\n<p>\u6700\u57fa\u672c\u7684\u6a21\u5f0f\u662f\u7528\u53cd\u5f15\u53f7\u5305\u88f9\u7684\u4ee3\u7801\u7247\u6bb5\uff1a<\/p>\n<pre><code class=\"gritql\">`console.log('Hello')`<\/code><\/pre>\n<p><strong>\u7ed3\u6784\u5316\u5339\u914d<\/strong>\u610f\u5473\u7740 Grit \u5ffd\u7565\u683c\u5f0f\u5dee\u5f02\uff0c\u4ee5\u4e0b\u90fd\u4f1a\u88ab\u5339\u914d\uff1a<\/p>\n<pre><code class=\"javascript\">console.log('Hello')\nconsole.log ( 'Hello' )     \/\/ \u6362\u884c\u548c\u7a7a\u683c\u4e0d\u5f71\u54cd\nconsole.log(&quot;Hello&quot;)         \/\/ \u5355\u53cc\u5f15\u53f7\u7b49\u4ef7<\/code><\/pre>\n<h3>\u53d8\u91cf\u7cfb\u7edf<\/h3>\n<p>\u4f7f\u7528 <code>$<\/code> \u524d\u7f00\u5b9a\u4e49\u53d8\u91cf\uff0c\u5339\u914d\u4efb\u610f\u5185\u5bb9\uff1a<\/p>\n<pre><code class=\"gritql\">`console.$method($msg)`      \/\/ \u5339\u914d console \u7684\u4efb\u4f55\u65b9\u6cd5\u8c03\u7528<\/code><\/pre>\n<p><strong>\u53d8\u91cf\u590d\u7528\u89c4\u5219<\/strong>\uff1a\u540c\u4e00\u53d8\u91cf\u591a\u6b21\u51fa\u73b0\u5fc5\u987b\u5339\u914d\u76f8\u540c\u503c<\/p>\n<pre><code class=\"gritql\">`$obj &amp;&amp; $obj.$prop()`       \/\/ foo &amp;&amp; foo.bar() \u2713\n                              \/\/ foo &amp;&amp; bar.baz()   \u2717<\/code><\/pre>\n<h3>\u6761\u4ef6\u8fc7\u6ee4<\/h3>\n<p>\u4f7f\u7528 <code>where<\/code> \u5b50\u53e5\u7cbe\u786e\u63a7\u5236\u5339\u914d\u8303\u56f4\uff1a<\/p>\n<pre><code class=\"gritql\">`console.$method($msg)` where {\n  $method &lt;: or { `log`, `warn` }    \/\/ \u53ea\u5339\u914d log \u548c warn\n}<\/code><\/pre>\n<h3>\u8f6c\u6362\u8bed\u6cd5<\/h3>\n<p>\u4f7f\u7528 <code>=&gt;<\/code> \u8fdb\u884c\u4ee3\u7801\u8f6c\u6362\uff1a<\/p>\n<pre><code class=\"gritql\">`\u65e7\u4ee3\u7801($args)` =&gt; `\u65b0\u4ee3\u7801($args)`<\/code><\/pre>\n<hr>\n<h2>\u5b9e\u6218\u6848\u4f8b<\/h2>\n<h3>\u6848\u4f8b 1\uff1a\u6e05\u7406 console \u8c03\u8bd5\u8bed\u53e5<\/h3>\n<p>\u6700\u7b80\u5355\u7684\u573a\u666f \u2014\u2014 \u76f4\u63a5\u5220\u9664\u5339\u914d\u7684\u4ee3\u7801\u3002<\/p>\n<pre><code class=\"javascript\">\/\/ \u8f6c\u6362\u524d\nconsole.log('fetching data...');\nconsole.debug('state:', state);\nconsole.info('API called');\nconsole.error('Critical error');  \/\/ \u4fdd\u7559\n\n\/\/ \u8f6c\u6362\u540e\nconsole.error('Critical error');<\/code><\/pre>\n<p><strong>\u4f7f\u7528\u6807\u51c6\u5e93 pattern\uff08\u63a8\u8350\uff09<\/strong>\uff1a<\/p>\n<pre><code class=\"bash\">grit apply no_console_log src\/<\/code><\/pre>\n<p><strong>\u81ea\u5b9a\u4e49 GritQL \u89c4\u5219<\/strong>\uff1a<\/p>\n<pre><code class=\"gritql\">`console.log($a)` =&gt; ``\n`console.debug($a)` =&gt; ``\n`console.info($a)` =&gt; ``<\/code><\/pre>\n<blockquote><p><strong>\u6ce8\u610f<\/strong>: \u6807\u51c6\u5e93\u7684 <code>no_console_log<\/code> \u4f1a\u81ea\u52a8\u4fdd\u7559 catch \u5757\u4e2d\u7684 console.log\uff0c\u66f4\u52a0\u5b89\u5168\u3002<\/p><\/blockquote>\n<hr>\n<h3>\u6848\u4f8b 2\uff1aPython print \u8f6c logger<\/h3>\n<p>\u5c06 Python \u4e2d\u7684 <code>print<\/code> \u8bed\u53e5\u8f6c\u6362\u4e3a logger \u8c03\u7528\u3002<\/p>\n<pre><code class=\"python\"># \u8f6c\u6362\u524d\nprint(&quot;Hello, World&quot;)\nprint(f&quot;User: {username}&quot;)\nprint(&quot;Error:&quot;, error)\n\n# \u8f6c\u6362\u540e\nlog(&quot;Hello, World&quot;)\nlog(f&quot;User: {username}&quot;)\nlog(&quot;Error:&quot;, error)<\/code><\/pre>\n<p><strong>\u4f7f\u7528\u6807\u51c6\u5e93 pattern<\/strong>\uff1a<\/p>\n<pre><code class=\"bash\">grit apply --language python print_to_log src\/<\/code><\/pre>\n<hr>\n<h3>\u6848\u4f8b 3\uff1a\u79fb\u9664 debugger \u8bed\u53e5<\/h3>\n<p>\u6e05\u7406\u5f00\u53d1\u65f6\u7559\u4e0b\u7684 debugger \u8bed\u53e5\u3002<\/p>\n<pre><code class=\"javascript\">\/\/ \u8f6c\u6362\u524d\nfunction processData(data) {\n    debugger;  \/\/ \u8c03\u8bd5\u7528\n    return data.map(x =&gt; x * 2);\n}\n\n\/\/ \u8f6c\u6362\u540e\nfunction processData(data) {\n    return data.map(x =&gt; x * 2);\n}<\/code><\/pre>\n<p><strong>\u4f7f\u7528\u6807\u51c6\u5e93 pattern<\/strong>\uff1a<\/p>\n<pre><code class=\"bash\">grit apply no_debugger src\/<\/code><\/pre>\n<hr>\n<h3>\u6848\u4f8b 4\uff1aimport \u8def\u5f84\u8c03\u6574<\/h3>\n<p>\u9879\u76ee\u76ee\u5f55\u91cd\u6784\u65f6\u7684\u5e38\u89c1\u9700\u6c42 \u2014\u2014 \u6279\u91cf\u66f4\u65b0 import \u8def\u5f84\u3002<\/p>\n<pre><code class=\"javascript\">\/\/ \u8f6c\u6362\u524d\nimport { Button } from '@\/components\/ui\/Button'\nimport { useAuth } from '@\/hooks\/useAuth'\nimport { formatDate } from '@\/utils\/date'\n\n\/\/ \u8f6c\u6362\u540e\nimport { Button } from '@\/components\/Button'\nimport { useAuth } from '@\/hooks\/auth'\nimport { formatDate } from '@\/utils\/format'<\/code><\/pre>\n<p><strong>GritQL \u89c4\u5219<\/strong>\uff1a<\/p>\n<pre><code class=\"gritql\">`from '@\/components\/ui\/$name'` =&gt; `from '@\/components\/$name'`\n`from '@\/hooks\/use$name'` =&gt; `from '@\/hooks\/$name'`\n`from '@\/utils\/date'` =&gt; `from '@\/utils\/format'`<\/code><\/pre>\n<hr>\n<h3>\u6848\u4f8b 5\uff1a\u7bad\u5934\u51fd\u6570\u7b80\u5316<\/h3>\n<blockquote><p>\u26a0\ufe0f <strong>\u9650\u5236<\/strong>\uff1a\u5185\u8054 pattern \u5bf9\u591a\u53c2\u6570\u51fd\u6570\u7684\u5904\u7406\u6709\u9650\u5236\uff0c\u5efa\u8bae\u4ec5\u7528\u4e8e\u5355\u53c2\u6570\u573a\u666f\u3002<\/p><\/blockquote>\n<p>\u5355\u884c\u8fd4\u56de\u7684\u7bad\u5934\u51fd\u6570\u53ef\u4ee5\u7701\u7565 <code>return<\/code> \u548c\u5927\u62ec\u53f7\u3002<\/p>\n<pre><code class=\"javascript\">\/\/ \u8f6c\u6362\u524d\nconst double = x =&gt; { return x * 2; }\nconst getValue = () =&gt; { return config.value; }\n\n\/\/ \u8f6c\u6362\u540e\nconst double = x =&gt; x * 2\nconst getValue = () =&gt; config.value<\/code><\/pre>\n<p><strong>\u5f02\u6b65\u7bad\u5934\u51fd\u6570<\/strong>\uff1a\u53ef\u4ee5\u53bb\u9664 <code>async<\/code> \u548c <code>await<\/code>\uff08\u5f53\u76f4\u63a5\u8fd4\u56de Promise \u65f6\uff09\u3002<\/p>\n<pre><code class=\"javascript\">\/\/ \u8f6c\u6362\u524d\nconst getData = async () =&gt; { return await fetch('\/api\/data'); }\n\n\/\/ \u8f6c\u6362\u540e\nconst getData = () =&gt; fetch('\/api\/data')<\/code><\/pre>\n<blockquote><p><strong>\u8bf4\u660e<\/strong>\uff1a\u5f53\u51fd\u6570\u53ea\u662f\u76f4\u63a5\u8fd4\u56de <code>await<\/code> \u7684\u7ed3\u679c\u65f6\uff0c<code>async\/await<\/code> \u662f\u5197\u4f59\u7684\u3002<\/p><\/blockquote>\n<p><strong>GritQL \u89c4\u5219<\/strong>\uff1a<\/p>\n<pre><code class=\"gritql\"># \u5355\u53c2\u6570\u7bad\u5934\u51fd\u6570\uff08\u63a8\u8350\uff09\n`$param =&gt; { return $expr }` =&gt; `$param =&gt; $expr`\n\n# \u65e0\u53c2\u6570\u7bad\u5934\u51fd\u6570\n`() =&gt; { return $expr }` =&gt; `() =&gt; $expr`\n\n# \u5f02\u6b65\u7bad\u5934\u51fd\u6570 - \u53bb\u9664 async\/await\n`async () =&gt; { return await $expr }` =&gt; `() =&gt; $expr`<\/code><\/pre>\n<p><strong>\u6ce8\u610f<\/strong>\uff1a\u591a\u53c2\u6570\u51fd\u6570 <code>(a, b) =&gt; ...<\/code> \u7684\u8f6c\u6362\u5b58\u5728\u62ec\u53f7\u5904\u7406\u95ee\u9898\uff0c\u5efa\u8bae\u624b\u52a8\u5904\u7406\u6216\u4f7f\u7528 .grit \u6587\u4ef6\u3002<\/p>\n<hr>\n<h3>\u6848\u4f8b 6\uff1a\u6846\u67b6\u5347\u7ea7\u8fc1\u79fb<\/h3>\n<p>Grit \u63d0\u4f9b\u4e86\u4e30\u5bcc\u7684\u6846\u67b6\u5347\u7ea7 patterns\uff0c\u53ef\u81ea\u52a8\u5316\u5e38\u89c1\u7684\u8fc1\u79fb\u5de5\u4f5c\u3002<\/p>\n<h4>React \u5347\u7ea7<\/h4>\n<table>\n<thead>\n<tr>\n<th>\u8fc1\u79fb\u7c7b\u578b<\/th>\n<th>Pattern<\/th>\n<th>\u547d\u4ee4<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>\u7c7b\u7ec4\u4ef6 \u2192 Hooks<\/td>\n<td><code>react_to_hooks<\/code><\/td>\n<td><code>grit apply react_to_hooks src\/<\/code><\/td>\n<\/tr>\n<tr>\n<td>React Query v3 \u2192 v4<\/td>\n<td><code>migrating_from_react_query_3_to_react_query_4<\/code><\/td>\n<td><code>grit apply migrating_from_react_query_3_to_react_query_4 src\/<\/code><\/td>\n<\/tr>\n<tr>\n<td>MUI v4 \u2192 v5<\/td>\n<td><code>mui4_to_mui5<\/code><\/td>\n<td><code>grit apply mui4_to_mui5 src\/<\/code><\/td>\n<\/tr>\n<tr>\n<td>Knockout \u2192 React<\/td>\n<td><code>knockout_to_react<\/code><\/td>\n<td><code>grit apply knockout_to_react src\/<\/code><\/td>\n<\/tr>\n<tr>\n<td>Jest \u2192 Vitest<\/td>\n<td><code>jest_to_vitest<\/code><\/td>\n<td><code>grit apply jest_to_vitest src\/<\/code><\/td>\n<\/tr>\n<tr>\n<td>Chai \u2192 Jest<\/td>\n<td><code>chai_to_jest<\/code><\/td>\n<td><code>grit apply chai_to_jest src\/<\/code><\/td>\n<\/tr>\n<tr>\n<td>Enzyme \u2192 RTL<\/td>\n<td><code>enzyme_rtl<\/code><\/td>\n<td><code>grit apply enzyme_rtl src\/<\/code><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p><strong>React \u7c7b\u7ec4\u4ef6\u8f6c Hooks \u793a\u4f8b<\/strong>\uff1a<\/p>\n<pre><code class=\"javascript\">\/\/ \u8f6c\u6362\u524d\nclass UserList extends React.Component {\n  state = { users: [], loading: false }\n  componentDidMount() {\n    this.fetchUsers()\n  }\n  fetchUsers() {\n    this.setState({ loading: true })\n    api.getUsers().then(users =&gt; this.setState({ users, loading: false }))\n  }\n  render() {\n    if (this.state.loading) return &lt;div&gt;Loading...&lt;\/div&gt;\n    return &lt;div&gt;{this.state.users.length} users&lt;\/div&gt;\n  }\n}\n\n\/\/ \u8f6c\u6362\u540e\nfunction UserList() {\n  const [users, setUsers] = useState([])\n  const [loading, setLoading] = useState(false)\n\n  useEffect(() =&gt; {\n    fetchUsers()\n  }, [])\n\n  function fetchUsers() {\n    setLoading(true)\n    api.getUsers().then(data =&gt; { setUsers(data); setLoading(false) })\n  }\n\n  if (loading) return &lt;div&gt;Loading...&lt;\/div&gt;\n  return &lt;div&gt;{users.length} users&lt;\/div&gt;\n}<\/code><\/pre>\n<p><strong>\u4f7f\u7528\u547d\u4ee4<\/strong>\uff1a<\/p>\n<pre><code class=\"bash\"># \u9884\u89c8\u8f6c\u6362\u7ed3\u679c\ngrit apply --dry-run react_to_hooks src\/\n\n# \u6267\u884c\u8f6c\u6362\ngrit apply react_to_hooks src\/\n\n# \u4ea4\u4e92\u5f0f\u9009\u62e9\uff08\u9010\u4e2a\u786e\u8ba4\uff09\ngrit apply --interactive react_to_hooks src\/<\/code><\/pre>\n<h4>Vue \u5347\u7ea7<\/h4>\n<p>Vue \u76f8\u5173\u7684\u8fc1\u79fb pattern \u8f83\u5c11\uff0c\u5efa\u8bae\u624b\u52a8\u6216\u914d\u5408\u5176\u4ed6\u5de5\u5177\u8fdb\u884c Vue 2 \u2192 Vue 3 \u7684\u5347\u7ea7\u3002<\/p>\n<h4>\u5176\u4ed6\u8fc1\u79fb<\/h4>\n<table>\n<thead>\n<tr>\n<th>\u8fc1\u79fb\u7c7b\u578b<\/th>\n<th>Pattern<\/th>\n<th>\u547d\u4ee4<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>Cypress \u2192 Playwright<\/td>\n<td><code>cypress_to_playwright<\/code><\/td>\n<td><code>grit apply cypress_to_playwright src\/<\/code><\/td>\n<\/tr>\n<tr>\n<td>Protractor \u2192 Playwright<\/td>\n<td><code>protractor_to_playwright<\/code><\/td>\n<td><code>grit apply protractor_to_playwright src\/<\/code><\/td>\n<\/tr>\n<tr>\n<td>CodeceptJS \u2192 Playwright<\/td>\n<td><code>codecept_to_playwright<\/code><\/td>\n<td><code>grit apply codecept_to_playwright src\/<\/code><\/td>\n<\/tr>\n<tr>\n<td>Moment \u2192 date-fns<\/td>\n<td><code>moment_to_datefns<\/code><\/td>\n<td><code>grit apply moment_to_datefns src\/<\/code><\/td>\n<\/tr>\n<tr>\n<td>io-ts \u2192 Zod<\/td>\n<td><code>iots_to_zod<\/code><\/td>\n<td><code>grit apply iots_to_zod src\/<\/code><\/td>\n<\/tr>\n<tr>\n<td>OpenAI v3 \u2192 v4<\/td>\n<td><code>openai_v4<\/code><\/td>\n<td><code>grit apply openai_v4 src\/<\/code><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p><strong>\u4f7f\u7528\u793a\u4f8b<\/strong>\uff1a<\/p>\n<pre><code class=\"bash\"># Jest \u8fc1\u79fb\u5230 Vitest\ngrit apply --dry-run jest_to_vitest src\/\ngrit apply jest_to_vitest src\/\n\n# OpenAI SDK \u5347\u7ea7\ngrit apply --dry-run openai_v4 src\/\ngrit apply openai_v4 src\/\n\n# \u6d4b\u8bd5\u6846\u67b6\u8fc1\u79fb\uff08Cypress \u2192 Playwright\uff09\ngrit apply --dry-run cypress_to_playwright tests\/\ngrit apply cypress_to_playwright tests\/<\/code><\/pre>\n<hr>\n<h3>\u6848\u4f8b 7\uff1a\u5bf9\u8c61\u7b80\u5199\u5c5e\u6027<\/h3>\n<blockquote><p>\u26a0\ufe0f <strong>\u9650\u5236<\/strong>\uff1a\u5fc5\u987b\u4f7f\u7528 <code>.grit<\/code> \u6587\u4ef6\uff0c\u5185\u8054\u8bed\u6cd5\u4e0d\u652f\u6301\uff0c\u4e14\u8f6c\u6362\u540e\u9700\u8981\u4eba\u5de5\u68c0\u67e5\u3002<\/p><\/blockquote>\n<p>ES6 \u5141\u8bb8\u5c5e\u6027\u540d\u548c\u53d8\u91cf\u540d\u76f8\u540c\u65f6\u7701\u7565\u5192\u53f7\u3002<\/p>\n<pre><code class=\"javascript\">\/\/ \u8f6c\u6362\u524d\nconst user = { name: name, age: age, userId: id }\nreturn { data: data, isLoading: loading }\n\n\/\/ \u8f6c\u6362\u540e\nconst user = { name, age, userId: id }\nreturn { data, isLoading: loading }<\/code><\/pre>\n<p><strong>\u521b\u5efa <code>shorthand.grit<\/code> \u6587\u4ef6<\/strong>\uff1a<\/p>\n<pre><code class=\"grit\"># \u6307\u5b9a\u4f7f\u7528\u7684\u5f15\u64ce\u7248\u672c\uff08marzano \u662f Grit \u7684\u5339\u914d\u5f15\u64ce\uff09\nengine marzano(0.1)\n# \u6307\u5b9a\u76ee\u6807\u8bed\u8a00\nlanguage js\n\n`{ $props }` where {\n  $props &lt;: some {\n    `$k: $k` =&gt; `$k`\n  }\n}<\/code><\/pre>\n<blockquote><p><strong><code>engine marzano(0.1)<\/code><\/strong>\uff1aGrit \u7684\u5339\u914d\u5f15\u64ce\u7248\u672c\uff0c\u6240\u6709 <code>.grit<\/code> \u6587\u4ef6\u90fd\u9700\u8981\u5728\u5f00\u5934\u58f0\u660e\u3002<\/p><\/blockquote>\n<p><strong>\u4f7f\u7528\u65b9\u5f0f<\/strong>\uff1a<\/p>\n<pre><code class=\"bash\"># \u5e94\u7528\u8f6c\u6362\uff08\u53ef\u80fd\u9700\u8981\u8fd0\u884c\u591a\u6b21\u76f4\u5230\u6240\u6709\u5c5e\u6027\u90fd\u8f6c\u6362\u5b8c\u6210\uff09\ngrit apply shorthand.grit src\/<\/code><\/pre>\n<p><strong>\u6d4b\u8bd5\u7ed3\u679c<\/strong>\uff1a<\/p>\n<ul>\n<li>\u2705 \u53ef\u4ee5\u5339\u914d\u5e76\u8f6c\u6362 <code>{ name: name }<\/code> \u2192 <code>{ name }<\/code><\/li>\n<li>\u26a0\ufe0f \u591a\u4e2a\u5c5e\u6027\u9700\u8981\u8fd0\u884c\u591a\u6b21\u624d\u80fd\u5168\u90e8\u8f6c\u6362<\/li>\n<li>\u26a0\ufe0f \u8f6c\u6362\u540e\u5efa\u8bae\u4eba\u5de5\u68c0\u67e5\u7ed3\u679c<\/li>\n<\/ul>\n<hr>\n<h2>\u5e38\u7528\u6807\u51c6 Patterns<\/h2>\n<p>Grit \u63d0\u4f9b\u4e86\u4e30\u5bcc\u7684\u6807\u51c6 patterns \u5e93\uff0c\u4f7f\u7528 <code>grit list<\/code> \u67e5\u770b\u3002<\/p>\n<h3>JavaScript\/TypeScript \u5e38\u7528 Patterns<\/h3>\n<table>\n<thead>\n<tr>\n<th>Pattern<\/th>\n<th>\u8bf4\u660e<\/th>\n<th>\u547d\u4ee4<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td><code>no_console_log<\/code><\/td>\n<td>\u79fb\u9664 <code>console.log<\/code><\/td>\n<td><code>grit apply no_console_log<\/code><\/td>\n<\/tr>\n<tr>\n<td><code>no_debugger<\/code><\/td>\n<td>\u79fb\u9664 <code>debugger<\/code><\/td>\n<td><code>grit apply no_debugger<\/code><\/td>\n<\/tr>\n<tr>\n<td><code>no_alert<\/code><\/td>\n<td>\u79fb\u9664 <code>alert()<\/code><\/td>\n<td><code>grit apply no_alert<\/code><\/td>\n<\/tr>\n<tr>\n<td><code>no_commented_out_code<\/code><\/td>\n<td>\u79fb\u9664\u6ce8\u91ca\u4ee3\u7801<\/td>\n<td><code>grit apply no_commented_out_code<\/code><\/td>\n<\/tr>\n<tr>\n<td><code>es6_imports<\/code><\/td>\n<td>\u8f6c\u6362\u4e3a ES6 imports<\/td>\n<td><code>grit apply es6_imports<\/code><\/td>\n<\/tr>\n<tr>\n<td><code>es6_exports<\/code><\/td>\n<td>\u8f6c\u6362\u4e3a ES6 exports<\/td>\n<td><code>grit apply es6_exports<\/code><\/td>\n<\/tr>\n<tr>\n<td><code>jest_to_vitest<\/code><\/td>\n<td>Jest \u8fc1\u79fb\u5230 Vitest<\/td>\n<td><code>grit apply jest_to_vitest<\/code><\/td>\n<\/tr>\n<tr>\n<td><code>chai_to_jest<\/code><\/td>\n<td>Chai \u8fc1\u79fb\u5230 Jest<\/td>\n<td><code>grit apply chai_to_jest<\/code><\/td>\n<\/tr>\n<tr>\n<td><code>openai_v4<\/code><\/td>\n<td>OpenAI v4 \u8fc1\u79fb<\/td>\n<td><code>grit apply openai_v4<\/code><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h3>Python \u5e38\u7528 Patterns<\/h3>\n<table>\n<thead>\n<tr>\n<th>Pattern<\/th>\n<th>\u8bf4\u660e<\/th>\n<th>\u547d\u4ee4<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td><code>print_to_log<\/code><\/td>\n<td>print \u8f6c logger<\/td>\n<td><code>grit apply --language python print_to_log<\/code><\/td>\n<\/tr>\n<tr>\n<td><code>py_no_debugger<\/code><\/td>\n<td>\u79fb\u9664 <code>pdb.set_trace()<\/code><\/td>\n<td><code>grit apply py_no_debugger<\/code><\/td>\n<\/tr>\n<tr>\n<td><code>no_skipped_tests<\/code><\/td>\n<td>\u79fb\u9664\u8df3\u8fc7\u7684\u6d4b\u8bd5<\/td>\n<td><code>grit apply no_skipped_tests<\/code><\/td>\n<\/tr>\n<tr>\n<td><code>openai<\/code><\/td>\n<td>OpenAI SDK \u8fc1\u79fb<\/td>\n<td><code>grit apply openai<\/code><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<hr>\n<h2>\u652f\u6301\u7684\u8bed\u8a00<\/h2>\n<p>Grit \u652f\u6301\u4ee5\u4e0b\u7f16\u7a0b\u8bed\u8a00\uff08\u4f7f\u7528 <code>--language<\/code> \u9009\u9879\u6307\u5b9a\uff09\uff1a<\/p>\n<h3>\u8bed\u8a00\u5217\u8868<\/h3>\n<table>\n<thead>\n<tr>\n<th>\u6807\u8bc6\u7b26<\/th>\n<th>\u8bed\u8a00<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td><code>js<\/code><\/td>\n<td>JavaScript \/ TypeScript \/ JSX \/ TSX<\/td>\n<\/tr>\n<tr>\n<td><code>html<\/code><\/td>\n<td>HTML<\/td>\n<\/tr>\n<tr>\n<td><code>css<\/code><\/td>\n<td>CSS<\/td>\n<\/tr>\n<tr>\n<td><code>json<\/code><\/td>\n<td>JSON<\/td>\n<\/tr>\n<tr>\n<td><code>java<\/code><\/td>\n<td>Java<\/td>\n<\/tr>\n<tr>\n<td><code>kotlin<\/code><\/td>\n<td>Kotlin<\/td>\n<\/tr>\n<tr>\n<td><code>csharp<\/code><\/td>\n<td>C#<\/td>\n<\/tr>\n<tr>\n<td><code>python<\/code><\/td>\n<td>Python<\/td>\n<\/tr>\n<tr>\n<td><code>markdown<\/code><\/td>\n<td>Markdown<\/td>\n<\/tr>\n<tr>\n<td><code>go<\/code><\/td>\n<td>Go<\/td>\n<\/tr>\n<tr>\n<td><code>rust<\/code><\/td>\n<td>Rust<\/td>\n<\/tr>\n<tr>\n<td><code>ruby<\/code><\/td>\n<td>Ruby<\/td>\n<\/tr>\n<tr>\n<td><code>elixir<\/code><\/td>\n<td>Elixir<\/td>\n<\/tr>\n<tr>\n<td><code>solidity<\/code><\/td>\n<td>Solidity<\/td>\n<\/tr>\n<tr>\n<td><code>hcl<\/code><\/td>\n<td>HCL<\/td>\n<\/tr>\n<tr>\n<td><code>yaml<\/code><\/td>\n<td>YAML<\/td>\n<\/tr>\n<tr>\n<td><code>sql<\/code><\/td>\n<td>SQL<\/td>\n<\/tr>\n<tr>\n<td><code>vue<\/code><\/td>\n<td>Vue<\/td>\n<\/tr>\n<tr>\n<td><code>toml<\/code><\/td>\n<td>TOML<\/td>\n<\/tr>\n<tr>\n<td><code>php<\/code><\/td>\n<td>PHP<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h3>\u4f7f\u7528\u793a\u4f8b<\/h3>\n<pre><code class=\"bash\"># Python \u9879\u76ee - \u5c06 print \u8f6c\u6362\u4e3a logger\ngrit apply --language python print_to_log src\/\n\n# Go \u9879\u76ee - \u79fb\u9664 debugger \u8bed\u53e5\ngrit apply --language go no_debugger src\/\n\n# Java \u9879\u76ee - \u5217\u51fa\u53ef\u7528\u7684 Java patterns\ngrit list --language java\n\n# Rust \u9879\u76ee - \u5e94\u7528\u81ea\u5b9a\u4e49 pattern\ngrit apply --language rust .\/patterns\/custom.grit src\/\n\n# Vue \u9879\u76ee - \u68c0\u67e5\u4ee3\u7801\u89c4\u8303\ngrit check --language vue src\/\n\n# \u591a\u8bed\u8a00\u9879\u76ee - \u540c\u65f6\u5904\u7406\u591a\u79cd\u6587\u4ef6\u7c7b\u578b\ngrit apply --language js no_console_log src\/\ngrit apply --language python print_to_log src\/\n\n# \u67e5\u770b\u67d0\u4e2a\u8bed\u8a00\u7684\u53ef\u7528 patterns\ngrit patterns list --language python<\/code><\/pre>\n<hr>\n<h2>\u5de5\u4f5c\u6d41\u6700\u4f73\u5b9e\u8df5<\/h2>\n<h3>\u63a8\u8350\u5de5\u4f5c\u6d41\u7a0b<\/h3>\n<pre><code class=\"bash\"># 1. \u5217\u51fa\u53ef\u7528\u7684 patterns\ngrit list --language js\n\n# 2. \u67e5\u770b pattern \u8be6\u60c5\ngrit patterns describe no_console_log\n\n# 3. \u9884\u89c8\u6a21\u5f0f\uff08\u4e0d\u4f1a\u4fee\u6539\u6587\u4ef6\uff09\ngrit apply --dry-run no_console_log src\/\n\n# 4. \u9650\u5236\u8303\u56f4\u6d4b\u8bd5\ngrit apply no_console_log src\/components\/\n\n# 5. \u4ea4\u4e92\u5f0f\u5e94\u7528\uff08\u9010\u4e2a\u786e\u8ba4\uff09\ngrit apply --interactive no_console_log src\/\n\n# 6. \u786e\u8ba4\u540e\u6b63\u5f0f\u5e94\u7528\ngrit apply no_console_log src\/<\/code><\/pre>\n<h3>\u4f7f\u7528\u914d\u7f6e\u6587\u4ef6<\/h3>\n<p>\u521b\u5efa <code>.grit\/grit.yaml<\/code> \u7ba1\u7406\u9879\u76ee\u89c4\u5219\uff1a<\/p>\n<pre><code class=\"yaml\">patterns:\n  - no_console_log\n  - no_debugger\n  - .grit\/patterns\/**\/*.grit\n\nignored:\n  - node_modules\/**\n  - dist\/**\n  - build\/**\n  - &quot;**\/*.min.js&quot;\n\nenforcement:\n  level: fix<\/code><\/pre>\n<h3>CI \u96c6\u6210<\/h3>\n<p>\u5728 GitHub Actions \u4e2d\u96c6\u6210\u4ee3\u7801\u68c0\u67e5\uff1a<\/p>\n<pre><code class=\"yaml\">name: Grit Code Quality\n\non: [pull_request]\n\njobs:\n  grit-check:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions\/checkout@v3\n      - name: Install Grit\n        run: npm install -g @getgrit\/cli\n      - name: Check code patterns\n        run: grit check --github-actions<\/code><\/pre>\n<hr>\n<h2>\u5de5\u4f5c\u539f\u7406<\/h2>\n<h3>\u5904\u7406\u6d41\u7a0b<\/h3>\n<pre><code>\u6e90\u4ee3\u7801\n    \u2193\n\u250c\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\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n\u2502  Tree-sitter \u89e3\u6790\u5668                 \u2502\n\u2502  (\u591a\u8bed\u8a00\u652f\u6301\uff0c\u589e\u91cf\u89e3\u6790)              \u2502\n\u2514\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\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n    \u2193 AST\n\u250c\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\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n\u2502  Grit \u6a21\u5f0f\u5339\u914d\u5f15\u64ce                  \u2502\n\u2502  (\u53d8\u91cf\u7ed1\u5b9a\uff0c\u6761\u4ef6\u8fc7\u6ee4)                \u2502\n\u2514\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\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n    \u2193 \u5339\u914d\u7ed3\u679c\n\u250c\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\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n\u2502  AST \u8f6c\u6362\u5f15\u64ce                       \u2502\n\u2502  (\u8bed\u4e49\u4fdd\u6301\uff0c\u7ed3\u6784\u8f6c\u6362)                \u2502\n\u2514\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\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n    \u2193 \u4fee\u6539\u540e\u7684 AST\n\u250c\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\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510\n\u2502  \u4ee3\u7801\u751f\u6210\u5668                         \u2502\n\u2502  (\u4fdd\u7559\u683c\u5f0f\uff0c\u751f\u6210\u4ee3\u7801)                \u2502\n\u2514\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\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518\n    \u2193\n\u8f6c\u6362\u540e\u4ee3\u7801<\/code><\/pre>\n<h3>\u4e3a\u4ec0\u4e48\u6bd4\u6b63\u5219\u66f4\u5b89\u5168\uff1f<\/h3>\n<table>\n<thead>\n<tr>\n<th>\u7279\u6027<\/th>\n<th>\u6b63\u5219\u8868\u8fbe\u5f0f<\/th>\n<th>Grit<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>\u7406\u89e3\u4ee3\u7801\u7ed3\u6784<\/td>\n<td>\u274c<\/td>\n<td>\u2705<\/td>\n<\/tr>\n<tr>\n<td>\u5ffd\u7565\u7a7a\u767d\/\u5f15\u53f7\u5dee\u5f02<\/td>\n<td>\u274c<\/td>\n<td>\u2705<\/td>\n<\/tr>\n<tr>\n<td>\u53d8\u91cf\u7ed1\u5b9a\u4e0e\u590d\u7528<\/td>\n<td>\u274c<\/td>\n<td>\u2705<\/td>\n<\/tr>\n<tr>\n<td>AST \u611f\u77e5<\/td>\n<td>\u274c<\/td>\n<td>\u2705<\/td>\n<\/tr>\n<tr>\n<td>\u8bed\u4e49\u5b89\u5168<\/td>\n<td>\u274c<\/td>\n<td>\u2705<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<hr>\n<h2>\u5e38\u89c1\u95ee\u9898<\/h2>\n<p><strong>Q: \u8f6c\u6362\u4f1a\u7834\u574f\u4ee3\u7801\u683c\u5f0f\u5417\uff1f<\/strong><\/p>\n<p>A: \u4e0d\u4f1a\u3002Grit \u4fdd\u7559\u539f\u59cb\u683c\u5f0f\uff0c\u53ea\u4fee\u6539\u8bed\u4e49\u7ed3\u6784\u3002<\/p>\n<p><strong>Q: \u5185\u8054 pattern \u600e\u4e48\u5199\uff1f<\/strong><\/p>\n<p>A: \u4f7f\u7528\u5355\u5f15\u53f7\u5305\u88f9\u6574\u4e2a pattern\uff08\u53cd\u5f15\u53f7\u5185\u662f\u5339\u914d\u4ee3\u7801\uff09\uff1a<\/p>\n<pre><code class=\"bash\"># \u6b63\u786e - \u5355\u5f15\u53f7\u5305\u88f9\uff0cshell \u4e0d\u4f1a\u89e3\u6790\u53cd\u5f15\u53f7\ngrit apply '`console.log($_)`' file.js\n\n# \u9519\u8bef - shell \u4f1a\u5c1d\u8bd5\u6267\u884c\u53cd\u5f15\u53f7\u5185\u7684\u547d\u4ee4\ngrit apply `console.log($_)` file.js<\/code><\/pre>\n<p><strong>Q: \u5982\u4f55\u67e5\u770b\u6240\u6709\u53ef\u7528\u7684 patterns\uff1f<\/strong><\/p>\n<p>A: \u4f7f\u7528 <code>grit list<\/code> \u547d\u4ee4\uff1a<\/p>\n<pre><code class=\"bash\"># \u5217\u51fa\u6240\u6709\ngrit list\n\n# \u6309\u8bed\u8a00\u8fc7\u6ee4\ngrit list --language js\ngrit list --language python<\/code><\/pre>\n<p><strong>Q: <code>--json<\/code> \u548c <code>--jsonl<\/code> \u6709\u4ec0\u4e48\u533a\u522b\uff1f<\/strong><\/p>\n<p>A: <code>--json<\/code> \u76ee\u524d\u4e0d\u88ab <code>apply_pattern<\/code> \u652f\u6301\uff0c\u4f7f\u7528 <code>--jsonl<\/code> \u83b7\u53d6 JSON Lines \u683c\u5f0f\u8f93\u51fa\u3002<\/p>\n<p><strong>Q: \u5982\u4f55\u9650\u5236\u4fee\u6539\u6570\u91cf\uff1f<\/strong><\/p>\n<p>A: \u4f7f\u7528 <code>--limit<\/code> \u9009\u9879\uff1a<\/p>\n<pre><code class=\"bash\"># \u53ea\u4fee\u6539\u524d 10 \u5904\ngrit apply --limit 10 no_console_log src\/<\/code><\/pre>\n<p><strong>Q: \u5982\u4f55\u5b89\u5168\u5730\u8fdb\u884c\u5927\u89c4\u6a21\u8f6c\u6362\uff1f<\/strong><\/p>\n<p>A: \u5efa\u8bae\u6309\u4ee5\u4e0b\u6b65\u9aa4\uff1a<\/p>\n<ol>\n<li>\u5148\u7528 <code>--dry-run<\/code> \u9884\u89c8<\/li>\n<li>\u7528 <code>--limit<\/code> \u5c0f\u8303\u56f4\u6d4b\u8bd5<\/li>\n<li>\u7528 <code>--interactive<\/code> \u4ea4\u4e92\u5f0f\u786e\u8ba4<\/li>\n<li>\u786e\u8ba4\u65e0\u8bef\u540e\u6b63\u5f0f\u5e94\u7528<\/li>\n<\/ol>\n<hr>\n<h2>\u603b\u7ed3<\/h2>\n<p>Grit \u7684\u6838\u5fc3\u4ef7\u503c\u5728\u4e8e\uff1a<\/p>\n<ol>\n<li><strong>\u7b80\u5355<\/strong> &#8211; \u7528\u4ee3\u7801\u7247\u6bb5\u5199\u89c4\u5219\uff0c\u65e0\u9700\u61c2 AST<\/li>\n<li><strong>\u5b89\u5168<\/strong> &#8211; \u7ed3\u6784\u5316\u5339\u914d\uff0c\u4e0d\u4f1a\u8bef\u4f24\u4ee3\u7801<\/li>\n<li><strong>\u9ad8\u6548<\/strong> &#8211; \u79d2\u7ea7\u5b8c\u6210\u5927\u89c4\u6a21\u4ee3\u7801\u8fc1\u79fb<\/li>\n<li><strong>\u53ef\u7ef4\u62a4<\/strong> &#8211; \u89c4\u5219\u5373\u6587\u6863\uff0c\u6613\u4e8e review<\/li>\n<li><strong>\u4e30\u5bcc<\/strong> &#8211; \u5185\u7f6e\u5927\u91cf\u6807\u51c6 patterns\uff0c\u5f00\u7bb1\u5373\u7528<\/li>\n<\/ol>\n<p>\u4e0b\u6b21\u9047\u5230\u4ee3\u7801\u8fc1\u79fb\u4efb\u52a1\uff0c\u4e0d\u59a8\u8bd5\u8bd5 Grit\uff0c\u8ba9\u7e41\u7410\u7684\u91cd\u6784\u5de5\u4f5c\u53d8\u5f97\u8f7b\u677e\u9ad8\u6548\u3002<\/p>\n<hr>\n<h2>\u53c2\u8003\u8d44\u6e90<\/h2>\n<ul>\n<li><a href=\"https:\/\/link.segmentfault.com\/?enc=rIG%2BpJvQUxZafCgDEv%2FIrw%3D%3D.oz4i5mSjk7uQYnbbCKg6v%2BnuxL72GvQv19uNxUCjpeI%3D\" rel=\"nofollow noopener noreferrer\" target=\"_blank\">Grit \u5b98\u7f51<\/a><\/li>\n<li><a href=\"https:\/\/link.segmentfault.com\/?enc=KC5%2Frybn3zagWw%2FOIFQkUw%3D%3D.xLleTTqt2vSQQA09MV%2F10cbGzTZuVIdMBh%2B2X%2FP9u8U%3D\" rel=\"nofollow noopener noreferrer\" target=\"_blank\">Grit \u5b98\u65b9\u6587\u6863<\/a><\/li>\n<li><a href=\"https:\/\/link.segmentfault.com\/?enc=QeeGwTkC40Zg0Ob3Xi%2Fjig%3D%3D.FUvQjx3GVM00wv5v%2BR7aihw1rPV%2BbnuwzSJldtR2U1CGMaaJQ4aQiwY1x1ZF7jiw\" rel=\"nofollow noopener noreferrer\" target=\"_blank\">Grit \u6807\u51c6 Patterns \u5e93<\/a><\/li>\n<li><a href=\"https:\/\/link.segmentfault.com\/?enc=6e7Mcp%2BocVNLAl9pCL4%2Brw%3D%3D.CNUofce%2Fs4uXyFqmdAcDsQo6tyP1QhY7hyzphjiMw8JQkZbo3UZqqx4ivYpPoZ57\" rel=\"nofollow noopener noreferrer\" target=\"_blank\">Grit GitHub<\/a><\/li>\n<\/ul>\n<p><a href=\"https:\/\/segmentfault.com\/a\/1190000047510883\">https:\/\/segmentfault.com\/a\/1190000047510883<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u9762\u5bf9\u9700\u8981\u4fee\u6539\u6570\u767e\u4e2a\u6587\u4ef6\u7684\u4ee3\u7801\u8fc1\u79fb\uff0c\u4f60\u8fd8\u5728\u624b\u52a8\u4e00\u4e2a\u4e2a\u6539\u5417\uff1f\u4eca\u5929\u4ecb\u7ecd\u4e00\u6b3e\u80fd\u8ba9\u4ee3\u7801\u6279\u91cf\u91cd\u6784\u50cf\u67e5\u627e\u66ff\u6362\u4e00\u6837\u7b80\u5355\u7684\u5de5\u5177  [&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-10021154","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\/10021154","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=10021154"}],"version-history":[{"count":0,"href":"https:\/\/itmax.cn\/index.php?rest_route=\/wp\/v2\/posts\/10021154\/revisions"}],"wp:attachment":[{"href":"https:\/\/itmax.cn\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=10021154"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/itmax.cn\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=10021154"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/itmax.cn\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=10021154"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}