<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Daniel.xiao</title>
    <description>The latest articles on DEV Community by Daniel.xiao (@danieldx).</description>
    <link>https://dev.to/danieldx</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F249537%2F07f2cff7-30d1-4cf7-8830-07becb2fd75e.png</url>
      <title>DEV Community: Daniel.xiao</title>
      <link>https://dev.to/danieldx</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/danieldx"/>
    <language>en</language>
    <item>
      <title>Develop your own code generator in five minutes</title>
      <dc:creator>Daniel.xiao</dc:creator>
      <pubDate>Sat, 29 May 2021 16:16:04 +0000</pubDate>
      <link>https://dev.to/danieldx/develop-your-own-code-generator-in-five-minutes-59om</link>
      <guid>https://dev.to/danieldx/develop-your-own-code-generator-in-five-minutes-59om</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--n37QLetQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/71e4c3g7i9j2nq4ywmlu.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--n37QLetQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/71e4c3g7i9j2nq4ywmlu.jpeg" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This article is short but full of sincerity&lt;br&gt;&lt;br&gt;
You can read it in less than 2 minutes&lt;br&gt;&lt;br&gt;
Then there is a high probability that you will be amazed&lt;br&gt;&lt;br&gt;
It turned out to be so simple to develop your own code generator&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Tips&lt;/strong&gt;: This article is a continuation of "&lt;a href="https://dev.to/danieldx/the-new-generation-of-code-generator-26h1"&gt;The new generation of code generator&lt;/a&gt;". If you don’t know what &lt;code&gt;ncgen&lt;/code&gt; is, it’s best to read "&lt;a href="https://dev.to/danieldx/the-new-generation-of-code-generator-26h1"&gt;The new generation of code generator&lt;/a&gt;" first&lt;/p&gt;




&lt;p&gt;Daniel: Brother Egg, after the last time, according to the method you taught me, I configured a code generator that fully meets my needs in a few minutes. It is really powerful and simple.&lt;/p&gt;

&lt;p&gt;Mr. Egg: Just do it, I admire your hands-on ability&lt;/p&gt;

&lt;p&gt;Daniel: Thanks. But I came again with a question today&lt;/p&gt;

&lt;p&gt;Mr. Egg: Waiting for a long time&lt;/p&gt;

&lt;p&gt;Daniel: I hung up &lt;code&gt;ncgen-config.js&lt;/code&gt; in the cloud, and my friends complained that the command was too long to remember when using it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;ncgen https://raw.githubusercontent.com/daniel-dx/vue3-ncgen-demo/master/ncgen-config.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Look, is it a bit long? Do you have any good suggestions?&lt;/p&gt;

&lt;p&gt;Mr. Egg: Of course, &lt;code&gt;ncgen&lt;/code&gt; has already prepared a very fascinating plan for this&lt;/p&gt;

&lt;p&gt;Daniel: What fascinating plan? How charming is it? Tell me quickly please&lt;/p&gt;

&lt;p&gt;Mr. Egg: That's it - Rapid development of &lt;strong&gt;your own code generator&lt;/strong&gt; through &lt;code&gt;ncgen&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Daniel: Wo~, it belongs to me, it sounds cool. How to do it？&lt;/p&gt;




&lt;p&gt;Mr. Egg: Suppose we want to develop a code generator now, let's call it &lt;strong&gt;vue-ncgen-demo-cli&lt;/strong&gt;, guess how many steps to get it?&lt;/p&gt;

&lt;p&gt;Daniel: I guess, just one step.&lt;/p&gt;

&lt;p&gt;Mr. Egg: This is a bit too much, I can't do it, goodbye&lt;/p&gt;

&lt;p&gt;Daniel: Just kidding, Brother Egg, just say it&lt;/p&gt;

&lt;p&gt;Mr. Egg: Let's go three steps&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Step 1: Generate code generator project
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;yarn create @ncgen/app &lt;span class="c"&gt;# npm init @ncgen/app&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--sW2Z4_dK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wb63ex14emz36iyfbqlw.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--sW2Z4_dK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wb63ex14emz36iyfbqlw.gif" alt="create"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Step 2: Write the code generator logic&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Find &lt;code&gt;ncgen-config.js&lt;/code&gt; in the generated project and modify this configuration file according to the logic of your code generator&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The sample configuration is here: &lt;a href="https://github.com/daniel-dx/vue-ncgen-demo-cli/blob/master/ncgen-config.js"&gt;https://github.com/daniel-dx/vue-ncgen-demo-cli/blob/master/ncgen-config.js&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Here is a tip. When you need to add sub-commands, in addition to copy and paste, you can actually do it more elegantly through sub-commands.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;vue-ncgen-demo-cli
&lt;span class="nv"&gt;$ &lt;/span&gt;yarn create @ncgen/app add-sub &lt;span class="c"&gt;# # npm init @ncgen/app add-sub&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--cgy4NWt_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/v0v4blzuv9sd1qn5owk0.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--cgy4NWt_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/v0v4blzuv9sd1qn5owk0.gif" alt="b.gif"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Step 3: Release to the world
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;npm run release
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;Daniel: It's over?&lt;/p&gt;

&lt;p&gt;Mr. Egg: Yes, it's over, it's that simple&lt;/p&gt;

&lt;p&gt;Daniel: How should my friends use this code generator?&lt;/p&gt;

&lt;p&gt;Mr. Egg: Very simple, the example is as follows&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Installation&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;npm i vue-ncgen-demo-cli &lt;span class="nt"&gt;-g&lt;/span&gt;

&lt;span class="c"&gt;# Execute the main command to generate the scaffolding project&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;vue-ncgen-demo-cli

&lt;span class="c"&gt;# Execute subcommand to insert code&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;vue-ncgen-demo-cli add-component
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Daniel: Perfect, I can’t wait to develop my own code generator&lt;/p&gt;

&lt;p&gt;Mr. Egg: Looking forward to your feedback&lt;/p&gt;




&lt;p&gt;ncgen github: &lt;a href="https://github.com/daniel-dx/ncgen"&gt;https://github.com/daniel-dx/ncgen&lt;/a&gt; [Please star it]&lt;/p&gt;

&lt;p&gt;ncgen documentation: &lt;a href="https://daniel-dx.github.io/ncgen/"&gt;https://daniel-dx.github.io/ncgen/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Keywords: ncgen, scaffolding, generator, code generator&lt;/p&gt;

</description>
    </item>
    <item>
      <title>The new generation of code generator</title>
      <dc:creator>Daniel.xiao</dc:creator>
      <pubDate>Sun, 09 May 2021 11:54:10 +0000</pubDate>
      <link>https://dev.to/danieldx/the-new-generation-of-code-generator-26h1</link>
      <guid>https://dev.to/danieldx/the-new-generation-of-code-generator-26h1</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--PuZ0WS4A--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/d8a53e83571242f0b399dfdeb0b52819%257Etplv-k3u1fbpfcp-watermark.image" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--PuZ0WS4A--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/d8a53e83571242f0b399dfdeb0b52819%257Etplv-k3u1fbpfcp-watermark.image" alt="WX20210509-175440@2x.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Speaking from a scaffold
&lt;/h2&gt;

&lt;p&gt;Daniel: Recently I want to build a code generator that can quickly generate project codes. What recommendation does Brother Egg have?&lt;/p&gt;

&lt;p&gt;Mr. Egg: I have always used yeoman in the past, and it is an open source project that is nearly 10k stars. However, what I want to recommend to you today is not yeoman, but a new generation code generator &lt;a href="https://daniel-dx.github.io/ncgen/"&gt;&lt;code&gt;ncgen&lt;/code&gt;&lt;/a&gt;, it may seem more approachable.&lt;/p&gt;

&lt;p&gt;Daniel: I like the simple one the most. How does it work?&lt;/p&gt;

&lt;p&gt;Mr. Egg: Old rules, you say your needs, I will try to answer them one by one&lt;/p&gt;

&lt;h3&gt;
  
  
  First, you need a project template
&lt;/h3&gt;

&lt;p&gt;Daniel: I have a project template (for example: &lt;a href="https://github.com/daniel-dx/vue3-ncgen-demo.git"&gt;vue3-ncgen-demo&lt;/a&gt;), I hope all new projects come from this project template, so I only need to concentrate on maintaining this project template.&lt;/p&gt;

&lt;p&gt;Mr. Egg: OK, this is the function of the project scaffolding. Let's take a look at how &lt;code&gt;ncgen&lt;/code&gt; is processed.&lt;/p&gt;

&lt;p&gt;The first step is to install ncgen&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;npm i ncgen &lt;span class="nt"&gt;-g&lt;/span&gt; &lt;span class="c"&gt;# yarn global add ncgen&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The second step is to generate the configuration file &lt;code&gt;ncgen-config.js&lt;/code&gt;, which describes the logic of the code generator&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;ncgen genConf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Step 3 Modify &lt;code&gt;main.tmplSource&lt;/code&gt; in &lt;code&gt;ncgen-config.js&lt;/code&gt; to the url of the project template.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;main&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;tmplSource&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://github.com/daniel-dx/vue3-ncgen-demo.git&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Try it out:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ncgen ncgen-config.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://camo.githubusercontent.com/ca5a5dc46a9b4148dd97b52fb1fd6c95b5c751f75ccf59bb81015f9d3f817b7a/68747470733a2f2f70332d6a75656a696e2e62797465696d672e636f6d2f746f732d636e2d692d6b3375316662706663702f65313232353236626236663934306333386565396163663165633161623365387e74706c762d6b3375316662706663702d77617465726d61726b2e696d616765" class="article-body-image-wrapper"&gt;&lt;img src="https://camo.githubusercontent.com/ca5a5dc46a9b4148dd97b52fb1fd6c95b5c751f75ccf59bb81015f9d3f817b7a/68747470733a2f2f70332d6a75656a696e2e62797465696d672e636f6d2f746f732d636e2d692d6b3375316662706663702f65313232353236626236663934306333386565396163663165633161623365387e74706c762d6b3375316662706663702d77617465726d61726b2e696d616765" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Simple copying is not enough, modification is necessary
&lt;/h3&gt;

&lt;p&gt;Daniel: Whoops is good. However, the currently generated project is exactly the same as the project template, but it will always have its own information that is different from the project template, such as the name of the project, the name of the author, etc. I don’t want to modify these manually every time the project is generated.&lt;/p&gt;

&lt;p&gt;Mr. Egg: OK, the request is very reasonable. Since this information can only be provided by the person who created the project, we need to collect this information through some questions, and then we can make some modifications to the generated project based on this information. We modify the &lt;code&gt;main.prompt&lt;/code&gt; and &lt;code&gt;main.updateFiles&lt;/code&gt; in &lt;code&gt;ncgen-config.js&lt;/code&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Example description:&lt;br&gt;&lt;br&gt;
Perform string replacement on the &lt;code&gt;package.json&lt;/code&gt; file in the generated project, the rules are as follows:&lt;br&gt;&lt;br&gt;
Replace the string &lt;code&gt;vue3-ncgen-demo&lt;/code&gt; with the project name entered by the user&lt;br&gt;&lt;br&gt;
Replace the string &lt;code&gt;Daniel.xiao&lt;/code&gt; with the author name entered by the user&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;main&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;input&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;author&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;What is the author's name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;

    &lt;span class="p"&gt;...&lt;/span&gt;

    &lt;span class="na"&gt;updateFiles&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;package.json&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;answers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;$answers&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;api&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;vue3-ncgen-demo&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;answers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;projectNameObj&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;kebabCase&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Daniel.xiao&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;answers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;author&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://camo.githubusercontent.com/389f2870fb39d3538e773c62035291a9e3d7d07585d54272ee132e6d64c1f15f/68747470733a2f2f70392d6a75656a696e2e62797465696d672e636f6d2f746f732d636e2d692d6b3375316662706663702f34346530363866656138353734653338386233393634396363346530336338367e74706c762d6b3375316662706663702d77617465726d61726b2e696d616765" class="article-body-image-wrapper"&gt;&lt;img src="https://camo.githubusercontent.com/389f2870fb39d3538e773c62035291a9e3d7d07585d54272ee132e6d64c1f15f/68747470733a2f2f70392d6a75656a696e2e62797465696d672e636f6d2f746f732d636e2d692d6b3375316662706663702f34346530363866656138353734653338386233393634396363346530336338367e74706c762d6b3375316662706663702d77617465726d61726b2e696d616765" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Daniel: Hey, I noticed that the template engine is not used here, but the string replacement is used directly&lt;/p&gt;

&lt;p&gt;Mr. Egg: Yes, this design has a lot of meaning. Using a template engine to replace files may cause the project template itself to fail to run normally, because the template engine requires placeholders, and placeholders may cause code parsing errors&lt;/p&gt;

&lt;p&gt;Daniel: Yes, in this way the project template is just an ordinary project, and there is no need to make some template placeholder transformations.&lt;/p&gt;

&lt;h3&gt;
  
  
  What about extra files? please delete
&lt;/h3&gt;

&lt;p&gt;Daniel: Then I will continue. There are some template directories and files (such as module template directories, component template files) in my project template, but I don't want to see these templates in the generated project.&lt;/p&gt;

&lt;p&gt;Mr. Egg: OK, no problem, just delete the specified files and directories. Let's modify the &lt;code&gt;main.removeFiles&lt;/code&gt; in &lt;code&gt;ncgen-config.js&lt;/code&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Example description:&lt;br&gt;&lt;br&gt;
Delete the &lt;code&gt;ncgen-config.js&lt;/code&gt; and &lt;code&gt;src/components/base/Template.vue&lt;/code&gt; files in the generated project&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;main&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;removeFiles&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ncgen-config.js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;src/components/base/Template.vue&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  One-stop service: automatic installation of dependencies
&lt;/h3&gt;

&lt;p&gt;Daniel: I just noticed that the above example will automatically install dependencies when it runs. It should be installed with &lt;code&gt;npm&lt;/code&gt;, can this support &lt;code&gt;yarn&lt;/code&gt;? If I am a non-NodeJS project, such as Python, Go, etc., can I do it?&lt;/p&gt;

&lt;p&gt;Mr. Egg: Of course! The generated &lt;code&gt;ncgen-config.js&lt;/code&gt; uses &lt;code&gt;npm i&lt;/code&gt; to install dependencies by default. See the example below. If you want to change to &lt;code&gt;yarn&lt;/code&gt;, just change &lt;code&gt;command&lt;/code&gt; to &lt;code&gt;yarn install&lt;/code&gt;. And if it is Python, Go and other languages, you only need to change &lt;code&gt;command&lt;/code&gt; to the corresponding dependency installation command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;main&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;installDependencies&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;skip&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;tips&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Dependencies are being installed, it may take a few minutes&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;command&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;npm i&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Finally, give some friendly tips
&lt;/h3&gt;

&lt;p&gt;Daniel: That’s great. The project scaffolding was completed in just a few clicks. I think a friendly welcome and beautiful ending is needed in the end.&lt;/p&gt;

&lt;p&gt;Mr. Egg: Simply modify the &lt;code&gt;main.welcome&lt;/code&gt; and &lt;code&gt;main.complete&lt;/code&gt; as you wish&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;main&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;welcome&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Welcome to use (Vue 3 + TypeScript + Vite) project generator&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

    &lt;span class="p"&gt;...&lt;/span&gt;

    &lt;span class="na"&gt;complete&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Congratulations, the operation is successful&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  High-frequency use is not scaffolding
&lt;/h2&gt;

&lt;p&gt;Daniel: The scaffolding is done, but it is only used when building a new project. High-frequency operations are still part of the increase in code, such as adding a functional module, adding a component, adding an API, etc.&lt;/p&gt;

&lt;p&gt;Mr. Egg: I understand what you mean. Old rules, you ask me to answer&lt;/p&gt;

&lt;h3&gt;
  
  
  The code template exists in the project template
&lt;/h3&gt;

&lt;p&gt;Daniel: I want to add a new component to a project. I don't want to copy an existing component and then perform various operations to modify and delete the code. In fact, there is a component template in the project template&lt;/p&gt;

&lt;p&gt;Mr. Egg: OK. Let's first add a subcommand called &lt;code&gt;add-component&lt;/code&gt; in &lt;code&gt;ncgen-config.js&lt;/code&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Example description (assuming that the values ​​of category and name are'busi' and'demo' respectively):&lt;br&gt;&lt;br&gt;
&lt;code&gt;description&lt;/code&gt; is used to describe the function of a subcommand.&lt;br&gt;&lt;br&gt;
&lt;code&gt;api.listDirs&lt;/code&gt; This API is very useful for allowing users to choose where to insert the code.&lt;br&gt;&lt;br&gt;
The configuration of &lt;code&gt;addFilesTo&lt;/code&gt; will insert the src/components/base/Template.vue in the project template into the src/components/busi/Demo.vue file in the project.&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;sub&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;add-component&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Add vue component&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

      &lt;span class="na"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;list&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;choices&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;api&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;listDirs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;src/components/&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
          &lt;span class="p"&gt;},&lt;/span&gt;
          &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;category&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Please select the category&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;input&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;What is the component name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="nx"&gt;validate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;The component name is required&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
          &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;],&lt;/span&gt;

      &lt;span class="na"&gt;tmplSource&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://github.com/daniel-dx/vue3-ncgen-demo.git&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

      &lt;span class="na"&gt;addFilesTo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;answers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;$answers&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;src/components/base/Template.vue&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`src/components/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;answers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;category&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;answers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;nameObj&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;upperFirstCamelCase&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;.vue`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;};&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://camo.githubusercontent.com/7acb96a3fdffb99386744eac7ef6f59a166eab84b784de19dd4fdab31329c8ce/68747470733a2f2f70362d6a75656a696e2e62797465696d672e636f6d2f746f732d636e2d692d6b3375316662706663702f32336332616533636637343434373735623161636537616531643834616630617e74706c762d6b3375316662706663702d77617465726d61726b2e696d616765" class="article-body-image-wrapper"&gt;&lt;img src="https://camo.githubusercontent.com/7acb96a3fdffb99386744eac7ef6f59a166eab84b784de19dd4fdab31329c8ce/68747470733a2f2f70362d6a75656a696e2e62797465696d672e636f6d2f746f732d636e2d692d6b3375316662706663702f32336332616533636637343434373735623161636537616531643834616630617e74706c762d6b3375316662706663702d77617465726d61726b2e696d616765" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  The code template does not exist in the project template
&lt;/h3&gt;

&lt;p&gt;Daniel: Pretty. But for the existing projects, these projects are not from the project template, and I also want to add some sub-commands to generate part of the code for the project, how to do?&lt;/p&gt;

&lt;p&gt;Mr. Egg: The subcommand supports two ways to add files, one is the code template from the project template mentioned above, and the other is dynamically created by you. Both can be used at the same time. The following example demonstrates how to dynamically create a code file&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Example description (assuming that the values ​​of category and name are'busi' and'demo' respectively):&lt;br&gt;&lt;br&gt;
The configuration of &lt;code&gt;addFiles&lt;/code&gt; will create a src/components/busi/Demo.md file in the project. The content of this file is &lt;code&gt;# Demo&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;sub&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;add-component&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;addFiles&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;answers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;$answers&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;`src/components/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;answers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;category&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;answers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;nameObj&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;upperFirstCamelCase&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;.md`&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s2"&gt;`# &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;answers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;nameObj&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;upperFirstCamelCase&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
          &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;};&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Highly recommended replacement technique
&lt;/h3&gt;

&lt;p&gt;Daniel: Next, some file contents are modified (for example, when a page is added, the routing rules file will be automatically modified to register routes for the page), right? The operation is the same as the main command.&lt;/p&gt;

&lt;p&gt;Mr. Egg: Well savvy. A tip recommended here is to add some identification comments where you need to insert the fragment code, as shown in the &lt;strong&gt;src/App.vue&lt;/strong&gt; code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;template&amp;gt;
  &amp;lt;img alt="Vue logo" src="./assets/logo.png" /&amp;gt;
  &amp;lt;HelloWorld msg="Hello Vue 3 + TypeScript + Vite" /&amp;gt;
  &amp;lt;!-- Don't touch me-place component --&amp;gt;
&amp;lt;/template&amp;gt;

&amp;lt;script lang="ts"&amp;gt;
import {defineComponent} from'vue'
import HelloWorld from'./components/busi/HelloWorld.vue'
// &amp;lt;!-- Don't touch me-import component --&amp;gt;
export default defineComponent({
  name:'App',
  components: {
    HelloWorld,
    // &amp;lt;!-- Don't touch me-register component --&amp;gt;
  }
})
&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Cooperate with &lt;code&gt;api.insertBefore&lt;/code&gt; this API to insert the specified content before the specified matching position of the file&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;sub&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;updateFiles&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;answers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;$answers&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;src/App.vue&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;api&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;insertBefore&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;// &amp;lt;!-- Don't touch me-import component --&amp;gt;&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`import &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;answers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;nameObj&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;upperFirstCamelCase&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; from'./components/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;answers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;category&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;answers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;nameObj&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;upperFirstCamelCase&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;.vue'`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;// &amp;lt;!-- Don't touch me-register component --&amp;gt;&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;answers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;nameObj&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;upperFirstCamelCase&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;,`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;!-- Don't touch me-place component --&amp;gt;&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;answers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;nameObj&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;upperFirstCamelCase&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/&amp;gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="p"&gt;});&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;`src/components/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;answers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;category&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;answers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;nameObj&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;upperFirstCamelCase&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;.vue`&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
          &lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="nx"&gt;options&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;api&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;Template&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;answers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;nameObj&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;upperFirstCamelCase&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="p"&gt;});&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Daniel: Perfect. Thank you brother egg. I am now eager to try my first code generator&lt;/p&gt;

&lt;p&gt;Mr. Egg: Welcome, looking forward to your feedback&lt;/p&gt;

&lt;h2&gt;
  
  
  Written at the end
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Above - complete configuration
&lt;/h3&gt;

&lt;p&gt;For the complete configuration of &lt;code&gt;ncgen-config.js&lt;/code&gt; in the example, please view: &lt;a href="https://github.com/daniel-dx/vue3-ncgen-demo/blob/master/ncgen-config.js"&gt;https://github.com/daniel-dx/vue3-ncgen-demo/blob/master/ncgen-config.js&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Below - ncgen official website
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://daniel-dx.github.io/ncgen/"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--pxO5nYoT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://daniel-dx.github.io/ncgen/logo.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;Keywords: ncgen, scaffolding, generator, code generator&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Cooking a delicious CLI</title>
      <dc:creator>Daniel.xiao</dc:creator>
      <pubDate>Thu, 31 Oct 2019 11:57:32 +0000</pubDate>
      <link>https://dev.to/danieldx/cooking-a-delicious-cli-3ef0</link>
      <guid>https://dev.to/danieldx/cooking-a-delicious-cli-3ef0</guid>
      <description>&lt;p&gt;&lt;a href="https://camo.githubusercontent.com/2b53c0a61a44f86ab2aa8163233af407f5decb2b/68747470733a2f2f757365722d676f6c642d63646e2e786974752e696f2f323031392f31302f33312f313665316638313565643766616164633f773d3132383026683d38343726663d6a70656726733d353631313437" class="article-body-image-wrapper"&gt;&lt;img src="https://camo.githubusercontent.com/2b53c0a61a44f86ab2aa8163233af407f5decb2b/68747470733a2f2f757365722d676f6c642d63646e2e786974752e696f2f323031392f31302f33312f313665316638313565643766616164633f773d3132383026683d38343726663d6a70656726733d353631313437" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Written at the begining, I really want to write a recipe, and suffer from limited cooking ability, so the title is a lie, forgive me ​​^_~&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Today, let's talk about the development of the command-line interface (abbreviated as CLI, the following will replace the lengthy command-line interface nouns with CLI).&lt;/p&gt;

&lt;p&gt;After reading this article, you will have a more comprehensive understanding of developing a CLI from beginning to end.&lt;/p&gt;

&lt;p&gt;You can also bookmark this article. When you want to develop a CLI, come back and you will always find what you want.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Daniel: Cola and potato chips are ready, waiting for you to start&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;All right. Let's go! &amp;lt;(￣︶￣)↗[GO!]]&lt;/p&gt;




&lt;h2&gt;
  
  
  &amp;gt; Take the first step: Initialize the project
&lt;/h2&gt;

&lt;p&gt;Create an empty project directory (the following is an example of &lt;code&gt;cook-cli&lt;/code&gt;, so here we name it &lt;code&gt;cook-cli&lt;/code&gt;), then type the command at the directory path to initialize, the process is as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;mkdir &lt;/span&gt;cook-cli
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cd &lt;/span&gt;cook-cli
&lt;span class="nv"&gt;$ &lt;/span&gt;npm init &lt;span class="nt"&gt;--yes&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;npm init&lt;/code&gt; command will initialize the directory to a &lt;code&gt;Node.js&lt;/code&gt; project, which will generate a &lt;code&gt;package.json&lt;/code&gt; file in the &lt;code&gt;cook-cli&lt;/code&gt; directory.&lt;/p&gt;

&lt;p&gt;Adding &lt;code&gt;--yes&lt;/code&gt; will automatically answer all the questions that were asked during the initialization process. You can try to remove the parameter and answer them yourself.&lt;/p&gt;




&lt;h2&gt;
  
  
  &amp;gt; Through main line: CLI skeleton codes
&lt;/h2&gt;

&lt;p&gt;The project is initially complete, then we add the skeleton codes and let the CLI fly for a while.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Implementer&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We create the &lt;code&gt;src/index.js&lt;/code&gt; file, which is responsible for implementing the functional logic of the CLI. code show as below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;cli&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;I like cooking&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Spokesperson&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Then create the &lt;code&gt;bin/cook&lt;/code&gt; file, which is the executable entry file for the CLI and the spokesperson for the CLI in the executable environment. code show as below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/usr/bin/env node&lt;/span&gt;

require &lt;span class="o"&gt;=&lt;/span&gt; require&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'esm'&lt;/span&gt;&lt;span class="o"&gt;)(&lt;/span&gt;module /&lt;span class="k"&gt;*&lt;/span&gt;, options&lt;span class="k"&gt;*&lt;/span&gt;/&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
require&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'../src'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;.cli&lt;span class="o"&gt;(&lt;/span&gt;process.argv&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Careful, you will find that the &lt;code&gt;esm&lt;/code&gt; module is used here. Its function is to let us use the &lt;code&gt;ECMAScript modules&lt;/code&gt; specification to load modules directly in the JS source code, ie use &lt;code&gt;import&lt;/code&gt; and &lt;code&gt;export&lt;/code&gt; directly. The code in &lt;code&gt;src/index.js&lt;/code&gt; above can directly write &lt;code&gt;export&lt;/code&gt; thanks to this module.&lt;/p&gt;

&lt;p&gt;(Run &lt;code&gt;npm i esm&lt;/code&gt; in the project root path to install the module)&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;External publicity&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We have spokesperson, but we must be publicized. So add a &lt;code&gt;bin&lt;/code&gt; statement to &lt;code&gt;package.json&lt;/code&gt; to announce the existence of the spokesperson. as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"bin"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"cook"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"./bin/cook"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  &amp;gt; Frequent rehearsal: Local development and debugging
&lt;/h2&gt;

&lt;p&gt;Local development and debugging is essential before the CLI is available, so a convenient debugging way is necessary.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Daniel: Developing web applications, I can debug features through a browser. What did the CLI get?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The CLI is running on the terminal, so we have to register it as a local command line. The way is very simple, run the following command in the project root path:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;npm &lt;span class="nb"&gt;link&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command will register a &lt;code&gt;cook&lt;/code&gt; CLI in the local environment and link its execution logic codes to your project directory, so it will take effect as soon as you update the code.&lt;/p&gt;

&lt;p&gt;Try running the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;cook
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://camo.githubusercontent.com/4383a5f48ac5a5d4fbc40991eb56927e230b95f4/68747470733a2f2f757365722d676f6c642d63646e2e786974752e696f2f323031392f31302f33302f313665316266653461663532326566633f773d34373826683d353026663d67696626733d38383338" class="article-body-image-wrapper"&gt;&lt;img src="https://camo.githubusercontent.com/4383a5f48ac5a5d4fbc40991eb56927e230b95f4/68747470733a2f2f757365722d676f6c642d63646e2e786974752e696f2f323031392f31302f33302f313665316266653461663532326566633f773d34373826683d353026663d67696626733d38383338" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Daniel: Nice! But I still have a problem, I want to set a breakpoint in vscode to debug, which sometimes makes it easier to troubleshoot the problem.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;You are right. That is also very simple. &lt;/p&gt;

&lt;p&gt;Add the following configuration to vscode. The path is: &lt;code&gt;Debug &amp;gt; Add Configuration&lt;/code&gt;. Modify the value of &lt;code&gt;args&lt;/code&gt; according to the actual command parameters to be debugged.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"configurations"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"node"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"request"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"launch"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Cook"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"program"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"${workspaceFolder}/bin/cook"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"args"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"hello"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Fill&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;parameters&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;you&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;want&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;debug&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  &amp;gt; Intent recognition: parameters analysis
&lt;/h2&gt;

&lt;p&gt;Insert an episode: although you may use various CLIs at work, it is necessary to give a brief introduction to some of the terms that CLI refers to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Command and Subcommand
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# cook is a command&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;cook

&lt;span class="c"&gt;# start is the subcommand of cook&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;cook start
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Options
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# -V is an option for short flag mode (note: only one letter, multiple letters means multiple options)&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;cook &lt;span class="nt"&gt;-V&lt;/span&gt;

&lt;span class="c"&gt;# --version is the option for long name mode&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;cook &lt;span class="nt"&gt;--version&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Parameters
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# source.js and target.js are both parameters of the cp command&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;cp &lt;/span&gt;source.js target.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;In fact, subcommands are also parameters of the command&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Ok, from the above introduction, we know if we want to implement a CLI, the analysis of the input parameters (including subcommand, options, argument) can not escape, then we will face them.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;commander: Hey, brother, don't be afraid. I am here!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Yes, brother, it’s good to see you. Next, we will use the &lt;code&gt;commander&lt;/code&gt; module to parse the parameters. The process and example are as follows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Module installation
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm i commander
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;src/index.js example
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;......&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;program&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;commander&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;cli&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;program&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Just one sentence to get it, so cool.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Daniel: What about the input parameters? How to use it?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In the next example, we will use these parsed input parameters. So please don't worry about it now.&lt;/p&gt;




&lt;h2&gt;
  
  
  &amp;gt; Can't live without you: version and help
&lt;/h2&gt;

&lt;p&gt;The version and help information is a part of the CLI that must be provided, otherwise it is too unprofessional. Let's see how to achieve it.&lt;/p&gt;

&lt;p&gt;Modify &lt;code&gt;src/index.js&lt;/code&gt; with the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;program&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;commander&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;pkg&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../package.json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;cli&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;program&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;version&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;pkg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;version&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;-V, --version&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;usage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;&amp;lt;command&amp;gt; [options]&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nx"&gt;program&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It's done by chained calls to &lt;code&gt;program.version&lt;/code&gt; and &lt;code&gt;usage&lt;/code&gt;, and it's still cool.&lt;/p&gt;

&lt;p&gt;Try running the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;cook &lt;span class="nt"&gt;-V&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://camo.githubusercontent.com/35dba21017e90037ff35358c1b6a6a37dddfd4e1/68747470733a2f2f757365722d676f6c642d63646e2e786974752e696f2f323031392f31302f33302f313665316330356465656138633563333f773d33343626683d363326663d67696626733d37373436" class="article-body-image-wrapper"&gt;&lt;img src="https://camo.githubusercontent.com/35dba21017e90037ff35358c1b6a6a37dddfd4e1/68747470733a2f2f757365722d676f6c642d63646e2e786974752e696f2f323031392f31302f33302f313665316330356465656138633563333f773d33343626683d363326663d67696626733d37373436" alt=""&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;cook &lt;span class="nt"&gt;-h&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://camo.githubusercontent.com/29721ee168d3acdd491addd74a295aaeb73446c5/68747470733a2f2f757365722d676f6c642d63646e2e786974752e696f2f323031392f31302f33302f313665316330386630313537643839383f773d35333226683d31323526663d67696626733d3130363136" class="article-body-image-wrapper"&gt;&lt;img src="https://camo.githubusercontent.com/29721ee168d3acdd491addd74a295aaeb73446c5/68747470733a2f2f757365722d676f6c642d63646e2e786974752e696f2f323031392f31302f33302f313665316330386630313537643839383f773d35333226683d31323526663d67696626733d3130363136" alt=""&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  &amp;gt; Add a general: Add a subcommand
&lt;/h2&gt;

&lt;p&gt;Now let's start to enrich the functionality of the CLI, starting with adding a subcommand &lt;code&gt;start&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;It has a parameter &lt;code&gt;food&lt;/code&gt; and an option &lt;code&gt;--fruit&lt;/code&gt;, the code is as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;......&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;cli&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="p"&gt;.....&lt;/span&gt;

  &lt;span class="nx"&gt;program&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;command&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;start &amp;lt;food&amp;gt;&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;option&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;-f, --fruit &amp;lt;name&amp;gt;&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Fruit to be added&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;description&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Start cooking food&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;food&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;option&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`run start command`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`argument: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;food&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`option: fruit = &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;option&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fruit&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="nx"&gt;program&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above example demonstrates how to get the parsed input parameters. In &lt;code&gt;action&lt;/code&gt; you can get everything you want. What you want to do is up to you.&lt;/p&gt;

&lt;p&gt;Try running the subcommand:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;cook start pizza &lt;span class="nt"&gt;-f&lt;/span&gt; apple
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://camo.githubusercontent.com/dfb88e64eb49f2ca6bb46efdc9f8fda39bcbb404/68747470733a2f2f757365722d676f6c642d63646e2e786974752e696f2f323031392f31302f33302f313665316337616264643166643333343f773d34323626683d393526663d67696626733d3233383737" class="article-body-image-wrapper"&gt;&lt;img src="https://camo.githubusercontent.com/dfb88e64eb49f2ca6bb46efdc9f8fda39bcbb404/68747470733a2f2f757365722d676f6c642d63646e2e786974752e696f2f323031392f31302f33302f313665316337616264643166643333343f773d34323626683d393526663d67696626733d3233383737" alt=""&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  &amp;gt; Seeking foreign aid: Calling external commands
&lt;/h2&gt;

&lt;p&gt;Sometimes we need to call external commands in the CLI, such as &lt;code&gt;npm&lt;/code&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;execa: I am going to perform. ┏ (^ω^)=☞&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;Module installation
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;npm i execa
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;src/index.js example
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;......&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;execa&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;execa&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;cli&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="p"&gt;.....&lt;/span&gt;

  &lt;span class="nx"&gt;program&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;command&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;npm-version&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;description&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Display npm version&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;stdout&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;execa&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;npm -v&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Npm version:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;stdout&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="nx"&gt;program&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The above external command is called by &lt;code&gt;execa&lt;/code&gt; is &lt;code&gt;npm -v&lt;/code&gt;.  Let's print the version of &lt;code&gt;npm&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;cook npm-version
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://camo.githubusercontent.com/2767c254af5ec55b51a593f2ad01483ca8946c9d/68747470733a2f2f757365722d676f6c642d63646e2e786974752e696f2f323031392f31302f33302f313665316338363338343234326265343f773d34313826683d353326663d67696626733d3134363133" class="article-body-image-wrapper"&gt;&lt;img src="https://camo.githubusercontent.com/2767c254af5ec55b51a593f2ad01483ca8946c9d/68747470733a2f2f757365722d676f6c642d63646e2e786974752e696f2f323031392f31302f33302f313665316338363338343234326265343f773d34313826683d353326663d67696626733d3134363133" alt=""&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  &amp;gt; Promoting communication: providing human interaction
&lt;/h2&gt;

&lt;p&gt;Sometimes we want the CLI to interact with the user in a question-and-answer way, and the user can provide the information we want by inputting or selecting.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;At thie moment, a strong wind blew. &lt;code&gt;Inquirer.js&lt;/code&gt; ran on the colorful clouds.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;Module installation
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;npm i inquirer
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The most common scenarios are: text input, boolean option, radio, check. Examples are as follows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;src/index.js example
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;......&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;inquirer&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;inquirer&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;cli&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="p"&gt;......&lt;/span&gt;

  &lt;span class="nx"&gt;program&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;command&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ask&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;description&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Ask some questions&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;option&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;answers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;inquirer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;input&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;name&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;What is your name?&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;confirm&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;isAdult&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Are you over 18 years old?&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;checkbox&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;favoriteFrameworks&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;choices&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Vue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;React&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Angular&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
          &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;What are you favorite frameworks?&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;list&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;favoriteLanguage&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;choices&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Chinese&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;English&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Japanese&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
          &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;What is you favorite language?&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;]);&lt;/span&gt;
      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;your answers:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;answers&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="nx"&gt;program&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The code is simple, let's directly see the result:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://camo.githubusercontent.com/bcf53bd6b3c942de69b584959377018934907808/68747470733a2f2f757365722d676f6c642d63646e2e786974752e696f2f323031392f31302f33302f313665316361316437633062346135633f773d37303826683d31393126663d67696626733d3333343638" class="article-body-image-wrapper"&gt;&lt;img src="https://camo.githubusercontent.com/bcf53bd6b3c942de69b584959377018934907808/68747470733a2f2f757365722d676f6c642d63646e2e786974752e696f2f323031392f31302f33302f313665316361316437633062346135633f773d37303826683d31393126663d67696626733d3333343638" alt=""&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  &amp;gt; Reduce anxiety: display hints in processing
&lt;/h2&gt;

&lt;p&gt;The human interaction experience is very important. If you can't complete the work immediately, you need to feedback the progress of the user's current work in time, which can reduce the user's waiting anxiety.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;ora&lt;/code&gt; and &lt;code&gt;listr&lt;/code&gt; shoulder to shoulder, marching neatly, oncoming.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The first thing is &lt;code&gt;ora&lt;/code&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Module installation
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;npm i ora
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;src/index.js example
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;......&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;ora&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ora&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;cli&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="p"&gt;......&lt;/span&gt;

  &lt;span class="nx"&gt;program&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;command&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;wait&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;description&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Wait 5 secords&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;option&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;spinner&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ora&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Waiting 5 seconds&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;start&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
      &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

      &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;interval&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;setInterval&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nx"&gt;clearInterval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;interval&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="nx"&gt;spinner&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;stop&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
            &lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
          &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="nx"&gt;spinner&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`Waiting &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; seconds`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
          &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="nx"&gt;program&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here is the result:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://camo.githubusercontent.com/d5b2bbf3a416c83eba62bebecb4a89ceed7dd95f/68747470733a2f2f757365722d676f6c642d63646e2e786974752e696f2f323031392f31302f33302f313665316361646332623037643431333f773d33333526683d363226663d67696626733d3334363739" class="article-body-image-wrapper"&gt;&lt;img src="https://camo.githubusercontent.com/d5b2bbf3a416c83eba62bebecb4a89ceed7dd95f/68747470733a2f2f757365722d676f6c642d63646e2e786974752e696f2f323031392f31302f33302f313665316361646332623037643431333f773d33333526683d363226663d67696626733d3334363739" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;listr&lt;/code&gt; followed.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Module installation
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;npm i listr
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;src/index.js example
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;......&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Listr&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;listr&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;cli&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="p"&gt;......&lt;/span&gt;

  &lt;span class="nx"&gt;program&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;command&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;steps&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;description&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;some steps&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;option&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;tasks&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Listr&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Run step 1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;task&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
            &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
              &lt;span class="nx"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;1 Done&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="p"&gt;})&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Run step 2&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;task&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
            &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
              &lt;span class="nx"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;2 Done&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="p"&gt;})&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Run step 3&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;task&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
            &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
              &lt;span class="nx"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Oh, my god&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="p"&gt;})&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;]);&lt;/span&gt;

      &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;tasks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;run&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="nx"&gt;program&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Still directly to see the result:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://camo.githubusercontent.com/914f7269ef1aaa371aa21044ccea6a0875d0b849/68747470733a2f2f757365722d676f6c642d63646e2e786974752e696f2f323031392f31302f33302f313665316362343133663933656134613f773d33353126683d31303826663d67696626733d3232313339" class="article-body-image-wrapper"&gt;&lt;img src="https://camo.githubusercontent.com/914f7269ef1aaa371aa21044ccea6a0875d0b849/68747470733a2f2f757365722d676f6c642d63646e2e786974752e696f2f323031392f31302f33302f313665316362343133663933656134613f773d33353126683d31303826663d67696626733d3232313339" alt=""&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  &amp;gt; Colorful: Make life no longer monotonous
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;chalk&lt;/code&gt;: I am a literary youth, I live for art, It’s me. &amp;lt;(￣ˇ￣)//&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;Module installation
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;npm i chalk
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;src/index.js example
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;.....&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;chalk&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;chalk&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;


&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;cli&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;chalk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;yellow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;I like cooking&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

  &lt;span class="p"&gt;.....&lt;/span&gt;

&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With the color of the CLI, is it to make you feel more happy?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://camo.githubusercontent.com/9aa90ad9f701fe31bc20e5d426ab35e7ab47daec/68747470733a2f2f757365722d676f6c642d63646e2e786974752e696f2f323031392f31302f33302f313665316362373738393633383233363f773d31333926683d343726663d706e6726733d31363333" class="article-body-image-wrapper"&gt;&lt;img src="https://camo.githubusercontent.com/9aa90ad9f701fe31bc20e5d426ab35e7ab47daec/68747470733a2f2f757365722d676f6c642d63646e2e786974752e696f2f323031392f31302f33302f313665316362373738393633383233363f773d31333926683d343726663d706e6726733d31363333" alt=""&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  &amp;gt; Decoration door: Add a border
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;boxen&lt;/code&gt;: This is my masterpiece, look at me! &amp;lt;(ˉ^ˉ)&amp;gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;Module installation
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;npm i boxen
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;src/index.js example
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;......&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;boxen&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;boxen&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;cli&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;boxen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;chalk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;yellow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;I like cooking&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;padding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;}));&lt;/span&gt;

  &lt;span class="p"&gt;......&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;  
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Well, it looks professional:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://camo.githubusercontent.com/404c8eaa03dc1963743568ee60c5e78eebd3ddd9/68747470733a2f2f757365722d676f6c642d63646e2e786974752e696f2f323031392f31302f33302f313665316362616239326233343534363f773d31393826683d31313626663d706e6726733d32353530" class="article-body-image-wrapper"&gt;&lt;img src="https://camo.githubusercontent.com/404c8eaa03dc1963743568ee60c5e78eebd3ddd9/68747470733a2f2f757365722d676f6c642d63646e2e786974752e696f2f323031392f31302f33302f313665316362616239326233343534363f773d31393826683d31313626663d706e6726733d32353530" alt=""&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  &amp;gt; Announcement: Publish to everyone
&lt;/h2&gt;

&lt;p&gt;If you publish in &lt;code&gt;scope&lt;/code&gt; mode, for example &lt;code&gt;@daniel-dx/cook-cli&lt;/code&gt;. Then add the following configuration to &lt;code&gt;package.json&lt;/code&gt; to allow you to publish it smoothly (of course, if you are a paid member of npm, then this configuration can be ignore)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"publishConfig"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"access"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"public"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Go go go:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;npm publish
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;OK, you have already released your CLI to the world, now you can go to &lt;a href="https://www.npmjs.com/"&gt;https://www.npmjs.com/&lt;/a&gt; to check your CLI.&lt;/p&gt;




&lt;h2&gt;
  
  
  &amp;gt; Sweet reminder: You should upgrade now
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;update-notifier: I finally got to play. I have waited until the flowers have been thanked. X_X&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;Module installation
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;npm i update-notifier
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;src/index.js example
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;......&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;updateNotifier&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;update-notifier&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;pkg&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;../package.json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;cli&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;checkVersion&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="p"&gt;......&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;checkVersion&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;notifier&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;updateNotifier&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;pkg&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;updateCheckInterval&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;notifier&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;update&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;notifier&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;notify&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For local debugging, we will reduce the local CLI version, change the &lt;code&gt;version&lt;/code&gt; of &lt;code&gt;package.json&lt;/code&gt; to &lt;code&gt;0.0.9&lt;/code&gt;, and then run &lt;code&gt;cook&lt;/code&gt; to see the effect:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://camo.githubusercontent.com/78d8bdafdf30d0c492743c1add8974f107be8eb0/68747470733a2f2f757365722d676f6c642d63646e2e786974752e696f2f323031392f31302f33302f313665316362633961313961383230643f773d34313326683d32363226663d706e6726733d39303639" class="article-body-image-wrapper"&gt;&lt;img src="https://camo.githubusercontent.com/78d8bdafdf30d0c492743c1add8974f107be8eb0/68747470733a2f2f757365722d676f6c642d63646e2e786974752e696f2f323031392f31302f33302f313665316362633961313961383230643f773d34313326683d32363226663d706e6726733d39303639" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;o(&lt;em&gt;￣︶￣&lt;/em&gt;)o Perfect!&lt;/p&gt;




&lt;p&gt;The above details some of the necessary or common steps to develop a CLI.&lt;/p&gt;

&lt;p&gt;Of course, if you just want to develop a CLI quickly, you can consider to use frameworks such as &lt;code&gt;oclif&lt;/code&gt; that are created for the development of the CLI, out of the box.&lt;/p&gt;

&lt;p&gt;As a programmer, we need to pay some time and energy for the ins and outs of the solution, the understanding of past and present, so that we can be more practical and go further.&lt;/p&gt;

&lt;p&gt;Ok, that's all.&lt;/p&gt;

&lt;p&gt;Here is the sample source code: &lt;a href="https://github.com/daniel-dx/cook-cli"&gt;https://github.com/daniel-dx/cook-cli&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;┏(^0^)┛ goodbye my friends! ByeBye...&lt;/p&gt;

</description>
      <category>node</category>
      <category>javascript</category>
      <category>cli</category>
      <category>commmand</category>
    </item>
    <item>
      <title>React Hooks - How to use state safely</title>
      <dc:creator>Daniel.xiao</dc:creator>
      <pubDate>Tue, 22 Oct 2019 11:51:11 +0000</pubDate>
      <link>https://dev.to/danieldx/react-hooks-how-to-use-state-safely-3of3</link>
      <guid>https://dev.to/danieldx/react-hooks-how-to-use-state-safely-3of3</guid>
      <description>&lt;p&gt;&lt;a href="https://camo.githubusercontent.com/9198181ec02b925b879d9462722c16a47bc765c1/68747470733a2f2f7361666572696465346b6964732e636f6d2f77702d636f6e74656e742f75706c6f6164732f323031352f31322f6361722d736561742d7361666574792d66697273742e6a7067" class="article-body-image-wrapper"&gt;&lt;img src="https://camo.githubusercontent.com/9198181ec02b925b879d9462722c16a47bc765c1/68747470733a2f2f7361666572696465346b6964732e636f6d2f77702d636f6e74656e742f75706c6f6164732f323031352f31322f6361722d736561742d7361666574792d66697273742e6a7067" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Hi, Daniel, let's talk about "How to use state safely" today?&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Daniel: Safe? Is it dangerous to use the state of React Hooks? X_X I am so nervous now~&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Take it easy, man. About safety, I will give you an example. Without the example, it is difficult to explain it clearly.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Daniel: Ok. Does anyone reading this article know about React Hooks?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Maybe some one don't know much about it, so I will briefly introduce it:&lt;/p&gt;

&lt;p&gt;React Hooks is a good thing, it allows you to implement stateful components with pure functions, so you don't have to worry about whether the component is stateful or stateless, no need to hesitate between the pure function and the class implementation (of course, the benefits are many, not only this. I will write an article about "Why React Hooks" later.)&lt;/p&gt;

&lt;p&gt;Once you are on the way of React Hooks, you will encounter a variety of strange problems.&lt;/p&gt;

&lt;p&gt;This is normal, the birth of a new thing, always accompanied by various problems, and then constantly upgraded and grew up in the fight, and eventually became. . .&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Daniel: Hey, don’t pull away.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;🤪 If you have read the official documentation on React Hooks and have seen some examples inside, you may think that it is quite simple, it is just changed to use state with &lt;code&gt;useState&lt;/code&gt;, no difficulty.&lt;/p&gt;

&lt;p&gt;However, just in the moment you relax your vigilance, "danger" is quietly coming down in some corners.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Daniel: Where is the danger? Where ? Where ? Where ?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;😅 ~~&lt;/p&gt;

&lt;p&gt;For the state value to get, you may have got an old value that is not what you expected, that is, not the latest state value.&lt;/p&gt;

&lt;p&gt;You need to stay awake all the time to make it possible to get around these "dangers."&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Daniel: 😵&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;You look confused., I will give an example now.&lt;/p&gt;

&lt;p&gt;Example is coming: When you fill out some information on the form and then leave the form, you want to automatically save it as a draft, so you can restore it the next time you come in.&lt;/p&gt;

&lt;p&gt;The implementation of the simplified version is given below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React, { useState, useEffect } from "react";

export const UseStateDemoComp1 = () =&amp;gt; {
  const [name, setName] = useState('daniel');

  useEffect(function() {
    return () =&amp;gt; {
      saveDraft()
    }
  }, [])

  function saveDraft() {
    console.log('Save Draft:', name);
  }

  return (
    &amp;lt;div&amp;gt;
      &amp;lt;form&amp;gt;
        &amp;lt;input value={name} onChange={e =&amp;gt; setName(e.target.value)}&amp;gt;&amp;lt;/input&amp;gt;
      &amp;lt;/form&amp;gt;
    &amp;lt;/div&amp;gt;
  );
};

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The code seems to have no problem.&lt;/p&gt;

&lt;p&gt;The function passed to &lt;code&gt;useEffect&lt;/code&gt; returns a function that is equivalent to the original &lt;code&gt;componentWillUnmount&lt;/code&gt; lifecycle method, which is called only when the component is destroyed. We can execute some logic in the method, here call the &lt;code&gt;saveDraft&lt;/code&gt; method, get the value of the name state, and save.&lt;/p&gt;

&lt;p&gt;Did you find the problem? If not, then let's take a look at the picture and see what the problem is:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://camo.githubusercontent.com/b60cc696fd0b8c12983e4abe19e3729d4759c93f/68747470733a2f2f757365722d676f6c642d63646e2e786974752e696f2f323031392f31302f32322f313664663231656431326432346531343f773d37323426683d36313526663d67696626733d3238323133" class="article-body-image-wrapper"&gt;&lt;img src="https://camo.githubusercontent.com/b60cc696fd0b8c12983e4abe19e3729d4759c93f/68747470733a2f2f757365722d676f6c642d63646e2e786974752e696f2f323031392f31302f32322f313664663231656431326432346531343f773d37323426683d36313526663d67696626733d3238323133" alt="Demonstration"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Clicking the Toggle button will destroy the component, so the destroy action will be triggered. As you can see from the gif, we filled in "sarah", but in the method of destroying execution, the value obtained is "daniel".&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Daniel: Why is this? Shouldn't it be the latest value? 😶&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Because the dependency of &lt;code&gt;useEffect&lt;/code&gt; is an empty array, it will only be executed once during the entire component life cycle, that is, after the component finishes rendering for the first time, and the state value used in the &lt;code&gt;useEffect&lt;/code&gt; method is the latest state value at that time. Can be understood with a snapshot. In the next time, no matter how many times the component is re-rendered, it will not change the value of the state inside, because it is just the snapshot at that time.&lt;/p&gt;

&lt;p&gt;Some one may say that we can fix it by adding name to the array of &lt;code&gt;useEffect&lt;/code&gt; depends on it. as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;useEffect(function() {
    return () =&amp;gt; {
      saveDraft()
    }
}, [name])
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It seems to satisfy the needs, but there are still problems. Because I only want to save when the component exits, but the result is that once the form field value changes, it will be saved, and the save operation becomes very frequent.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://camo.githubusercontent.com/024dff7d9e2e33a7508642d9a73698c79beb9b63/68747470733a2f2f757365722d676f6c642d63646e2e786974752e696f2f323031392f31302f32322f313664663233323062613365373636323f773d37323426683d36313526663d67696626733d3238383339" class="article-body-image-wrapper"&gt;&lt;img src="https://camo.githubusercontent.com/024dff7d9e2e33a7508642d9a73698c79beb9b63/68747470733a2f2f757365722d676f6c642d63646e2e786974752e696f2f323031392f31302f32322f313664663233323062613365373636323f773d37323426683d36313526663d67696626733d3238383339" alt="Demonstration"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Daniel: So you want to say that React Hooks has nothing to do with this?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Of course not, the above requirements can be achieved by &lt;code&gt;useRef&lt;/code&gt; and &lt;code&gt;useEffect&lt;/code&gt;. How to achieve it? Try it yourself. When you implement it, you will find that the code is not only lengthy, but also poorly readable.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Daniel: Ok, start your show now.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;With the above example, here is a description of &lt;code&gt;safely using state&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;"Safely using state is that no matter when and where you read the value of state, it always meets your expectations, always the latest value, without you being careful to judge whether it will be an old value that has not been updated"&lt;/p&gt;

&lt;p&gt;The official provided custom hooks capabilities, it want to continue to improve Hooks through the efforts of the community.&lt;/p&gt;

&lt;p&gt;Next, we will use [&lt;a href="https://github.com/daniel-dx/nice-hooks"&gt;nice-hooks&lt;/a&gt;], the third-party custom Hooks open source project, using its &lt;code&gt;useSingleState&lt;/code&gt; instead of useState, here is the example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React, { useEffect } from "react";
import { useSingleState } from "nice-hooks";

export const DemoComp1 = () =&amp;gt; {
  const [state, setState] = useSingleState({
    name: 'daniel'
  });

  useEffect(function() {
    return () =&amp;gt; {
      saveDraft()
    }
  }, [])

  function saveDraft() {
    console.log('Save Draft:', state.name);
  }

  return (
    &amp;lt;div&amp;gt;
      &amp;lt;form&amp;gt;
        &amp;lt;input value={state.name} onChange={e =&amp;gt; setState({name: e.target.value})}&amp;gt;&amp;lt;/input&amp;gt;
      &amp;lt;/form&amp;gt;
    &amp;lt;/div&amp;gt;
  );
};

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's take a look at the effect directly. Perfect~&lt;/p&gt;

&lt;p&gt;&lt;a href="https://camo.githubusercontent.com/d0ffbb5c061600b87fb04a77fa405d319723e566/68747470733a2f2f757365722d676f6c642d63646e2e786974752e696f2f323031392f31302f32322f313664663233383465636666653630333f773d37323426683d36313526663d67696626733d3234303032" class="article-body-image-wrapper"&gt;&lt;img src="https://camo.githubusercontent.com/d0ffbb5c061600b87fb04a77fa405d319723e566/68747470733a2f2f757365722d676f6c642d63646e2e786974752e696f2f323031392f31302f32322f313664663233383465636666653630333f773d37323426683d36313526663d67696626733d3234303032" alt="Demonstration"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here is a hook about &lt;code&gt;useSingleState&lt;/code&gt;: it uses state like &lt;code&gt;this.state&lt;/code&gt; and &lt;code&gt;this.setState&lt;/code&gt; in the form of &lt;code&gt;class&lt;/code&gt;, so it's very easy to get started. The most important thing is that it can &lt;code&gt;safely&lt;/code&gt; use state and have the ability to &lt;code&gt;callback&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Finally, we use the hook &lt;code&gt;useLifeCycle&lt;/code&gt; to improve the code. Now, the code below is a lot better than using the official hooks directly.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React from "react";
import { useSingleState, useLifeCycle } from "nice-hooks";

export const DemoComp1 = () =&amp;gt; {
  const [state, setState] = useSingleState({
    name: 'daniel'
  });

  useLifeCycle({
    willUnmount() {
      saveDraft()
    }
  })

  function saveDraft() {
    console.log('Save Draft:', state.name);
  }

  return (
    &amp;lt;div&amp;gt;
      &amp;lt;form&amp;gt;
        &amp;lt;input value={state.name} onChange={e =&amp;gt; setState({name: e.target.value})}&amp;gt;&amp;lt;/input&amp;gt;
      &amp;lt;/form&amp;gt;
    &amp;lt;/div&amp;gt;
  );
};

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Time is really fast, and it’s time to say goodbye.&lt;/p&gt;

&lt;p&gt;If you feel that this article is ok, please give it a heart or clap.&lt;/p&gt;

&lt;p&gt;If you think &lt;a href="https://github.com/daniel-dx/nice-hooks"&gt;nice-hooks&lt;/a&gt; is helpful, please give it a ☆.&lt;/p&gt;

&lt;p&gt;ByeBye!&lt;/p&gt;




&lt;p&gt;Keywords: react, hooks, nice-hooks&lt;/p&gt;

</description>
      <category>react</category>
      <category>hooks</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Develop a form in one minute</title>
      <dc:creator>Daniel.xiao</dc:creator>
      <pubDate>Thu, 17 Oct 2019 08:52:31 +0000</pubDate>
      <link>https://dev.to/danieldx/develop-a-form-in-one-minute-3p31</link>
      <guid>https://dev.to/danieldx/develop-a-form-in-one-minute-3p31</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--lGhyNH2r--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://upload-images.jianshu.io/upload_images/2195795-fe69d968e77801c2%3FimageMogr2/auto-orient/strip%257CimageView2/2/w/1240" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--lGhyNH2r--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://upload-images.jianshu.io/upload_images/2195795-fe69d968e77801c2%3FimageMogr2/auto-orient/strip%257CimageView2/2/w/1240" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The previous article "&lt;a href="https://dev.to/danieldx/form-generation-scheme-from-a-json-schema-2b0e"&gt;How to choose a open source project that generate forms from a JSON schema&lt;/a&gt;" I recommend ncform, today I will talk about how to use ncform for development form fast.&lt;br&gt;&lt;br&gt;
&amp;lt;(￣︶￣)&amp;gt;。&lt;/p&gt;

&lt;p&gt;The form is actually a visual description of a data, presented to the user in a friendly way, to achieve the purpose of collecting information filled by the user.&lt;/p&gt;

&lt;p&gt;Today, let's put aside the traditional form development way to understand the new and efficient way to develop forms (after reading, you may be able to get rid of the boring form development career)&lt;br&gt;&lt;br&gt;
╰(￣▽￣)╭&lt;/p&gt;



&lt;ul&gt;
&lt;li&gt;Form development first step: know your data structure&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The following is the data structure of the form to be developed today, not complicated, but not simple&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  firstname: 'daniel',
  lastname: 'xiao',
  fullname: 'daniel.xiao',
  gender: 'man',
  language: [ 'english', 'chinese' ],
  birthday: '',
  luckyNum: 9,
  luckyColor: '',
  email: 'danieldx666@126.com',
  favoriteMusics: [
    {
      type: '',
      score: 5
    }
  ],
  remarks: ''
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;ul&gt;
&lt;li&gt;Form development second step: generate ncform schema&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We can quickly generate the basic structure of the ncform schema through the ncform schema generator.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://camo.githubusercontent.com/70996cb0290a7bfdbc8b8db48f11b382a2a19c6a/68747470733a2f2f757365722d676f6c642d63646e2e786974752e696f2f323031392f332f32322f313639613333333162303436366336373f773d3133323926683d35313926663d67696626733d313933343037" class="article-body-image-wrapper"&gt;&lt;img src="https://camo.githubusercontent.com/70996cb0290a7bfdbc8b8db48f11b382a2a19c6a/68747470733a2f2f757365722d676f6c642d63646e2e786974752e696f2f323031392f332f32322f313639613333333162303436366336373f773d3133323926683d35313926663d67696626733d313933343037" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;OK, in less than a few seconds, a form is generated.&lt;/p&gt;

&lt;p&gt;Of course, this form is now ready to use, but it's too simplistic, let's optimize it. &amp;lt;(￣︶￣)↗[GO!]&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;ncform provides a playground, you can copy the generated ncform schema to the playground for optimization. The following demos are all performed at the playground.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;ul&gt;
&lt;li&gt;Optimize the name field: let users fill in as little as possible&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--_NB3ysJT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-gold-cdn.xitu.io/2019/3/22/169a352d7c7191f6%3Fw%3D855%26h%3D299%26f%3Dgif%26s%3D88138" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--_NB3ysJT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-gold-cdn.xitu.io/2019/3/22/169a352d7c7191f6%3Fw%3D855%26h%3D299%26f%3Dgif%26s%3D88138" alt=""&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// The following is the configuration information of the modified related fields.&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;firstname&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;type&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;string&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ui&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;label&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;First Name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;columns&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;lastname&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;type&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;string&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ui&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;label&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Last Name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;columns&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;fullname&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;type&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;string&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;valueTemplate&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;dx: {{$root.firstname}} + '.' + {{$root.lastname}}&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ui&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;label&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Full Name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;ul&gt;
&lt;li&gt;Optimize the gender field: pick one of two, the best choice is radio&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Fkcb-RVd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-gold-cdn.xitu.io/2019/3/22/169a3a53dd452712%3Fw%3D855%26h%3D299%26f%3Dgif%26s%3D107407" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Fkcb-RVd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-gold-cdn.xitu.io/2019/3/22/169a3a53dd452712%3Fw%3D855%26h%3D299%26f%3Dgif%26s%3D107407" alt=""&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// The following is the configuration information of the modified related fields.&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;gender&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;type&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;string&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;default&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;man&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ui&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;label&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Gender&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;widget&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;radio&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;widgetConfig&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;enumSource&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
              &lt;span class="p"&gt;{&lt;/span&gt;
                  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;value&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;man&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;label&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Man&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
              &lt;span class="p"&gt;},&lt;/span&gt;
             &lt;span class="p"&gt;{&lt;/span&gt;
                  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;value&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;woman&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;label&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Woman&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
              &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;ul&gt;
&lt;li&gt;Optimize the language field: not too many items and support multiple choices, the check box is a good choice&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Iuh-apKt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-gold-cdn.xitu.io/2019/3/22/169a3af1d5247500%3Fw%3D855%26h%3D299%26f%3Dgif%26s%3D82719" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Iuh-apKt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-gold-cdn.xitu.io/2019/3/22/169a3af1d5247500%3Fw%3D855%26h%3D299%26f%3Dgif%26s%3D82719" alt=""&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// The following is the configuration information of the modified related fields.&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;language&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;type&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;array&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ui&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;label&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Language&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;widget&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;checkbox&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;widgetConfig&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;enumSource&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
                &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;label&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;English&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;value&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;eng&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
                &lt;span class="p"&gt;},&lt;/span&gt;
                &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;label&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Chinese&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;value&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;cn&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;ul&gt;
&lt;li&gt;Optimize the birthday field: date we will use the date picker&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--flVvOT9a--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-gold-cdn.xitu.io/2019/3/22/169a3b8910f18030%3Fw%3D855%26h%3D299%26f%3Dgif%26s%3D66192" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--flVvOT9a--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-gold-cdn.xitu.io/2019/3/22/169a3b8910f18030%3Fw%3D855%26h%3D299%26f%3Dgif%26s%3D66192" alt=""&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// The following is the configuration information of the modified related fields.&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;birthday&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;type&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;string&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ui&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;label&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Birthday&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;widget&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;date-picker&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;ul&gt;
&lt;li&gt;Optimize luckyNum and luckyColor: for numbers and colors, there are corresponding widgets&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--9yPg8Bny--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-gold-cdn.xitu.io/2019/3/22/169a3cee12d6f0d9%3Fw%3D855%26h%3D299%26f%3Dgif%26s%3D107758" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--9yPg8Bny--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-gold-cdn.xitu.io/2019/3/22/169a3cee12d6f0d9%3Fw%3D855%26h%3D299%26f%3Dgif%26s%3D107758" alt=""&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// The following is the configuration information of the modified related fields.&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;luckyNum&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;type&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;number&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ui&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;label&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Lucky Num&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;widget&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;input-number&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;luckyColor&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;type&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;string&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ui&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;label&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;lucky Color&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;widget&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;color-picker&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;ul&gt;
&lt;li&gt;Optimize the email field: For email, it is necessary to add a email format validation rule. Let's add another rule - required.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Ke0csD2t--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-gold-cdn.xitu.io/2019/3/22/169a3f6e0e6a7fb4%3Fw%3D855%26h%3D299%26f%3Dgif%26s%3D68953" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Ke0csD2t--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-gold-cdn.xitu.io/2019/3/22/169a3f6e0e6a7fb4%3Fw%3D855%26h%3D299%26f%3Dgif%26s%3D68953" alt=""&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// The following is the configuration information of the modified related fields.&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;email&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;type&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;string&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ui&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;label&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Email&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;rules&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;required&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;email&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;ul&gt;
&lt;li&gt;Optimize the favoriteMusics field: I think the table is quite nice.&lt;/li&gt;
&lt;li&gt;Optimize the type field: There are many items in the music type, so it's better to use the drop-down box&lt;/li&gt;
&lt;li&gt;Optimize the score field: give a few stars feels good&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--M8JmfSet--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-gold-cdn.xitu.io/2019/3/22/169a4120339fa21f%3Fw%3D855%26h%3D299%26f%3Dgif%26s%3D252975" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--M8JmfSet--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-gold-cdn.xitu.io/2019/3/22/169a4120339fa21f%3Fw%3D855%26h%3D299%26f%3Dgif%26s%3D252975" alt=""&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// The following is the configuration information of the modified related fields.&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;favoriteMusics&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;type&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;array&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;items&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;type&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;object&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;properties&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;type&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;type&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;string&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ui&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
              &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;label&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Type&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
              &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;widget&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;select&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
              &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;widgetConfig&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;enumSource&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
                    &lt;span class="p"&gt;{&lt;/span&gt;
                        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;value&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;label&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Pop Music&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
                    &lt;span class="p"&gt;},&lt;/span&gt;
                    &lt;span class="p"&gt;{&lt;/span&gt;
                        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;value&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;2&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;label&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Rock Music&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
                    &lt;span class="p"&gt;}&lt;/span&gt;
                  &lt;span class="p"&gt;]&lt;/span&gt;
              &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
          &lt;span class="p"&gt;},&lt;/span&gt;
          &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;score&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;type&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;number&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ui&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
              &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;label&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;score&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
              &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;widget&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;rate&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
          &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ui&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;label&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;favoriteMusics&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ui&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;label&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;favoriteMusics&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;showLegend&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;widget&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;array-table&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;ul&gt;
&lt;li&gt;Optimize the remarks field: people who write notes may write more, so the textarea is better.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--dUQ1D3SA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-gold-cdn.xitu.io/2019/3/22/169a41a9a3f6956e%3Fw%3D855%26h%3D299%26f%3Dgif%26s%3D45901" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--dUQ1D3SA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-gold-cdn.xitu.io/2019/3/22/169a41a9a3f6956e%3Fw%3D855%26h%3D299%26f%3Dgif%26s%3D45901" alt=""&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// The following is the configuration information of the modified related fields.&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;remarks&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;type&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;string&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ui&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;label&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;remarks&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;widget&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;textarea&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;Now, the ncform schema for this form has been finished, let’s take a big photo. ♪(^∇^*)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Xy-TPOQ---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-gold-cdn.xitu.io/2019/3/22/169a428cc1e3ba07%3Fw%3D656%26h%3D299%26f%3Dgif%26s%3D221931" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Xy-TPOQ---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-gold-cdn.xitu.io/2019/3/22/169a428cc1e3ba07%3Fw%3D656%26h%3D299%26f%3Dgif%26s%3D221931" alt=""&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;Advertising time: ncform v1.0.0 officially released ( Star the repo to support ncform if you like it. O (∩ _ ∩) O)&lt;/p&gt;

&lt;p&gt;Main update features:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Fully tested: This version incorporates a large number of automated tests to ensure the quality of the project.&lt;/li&gt;
&lt;li&gt;Automatic support for dx expressions: User-defined widget's widgetConfig automatically supports dx expressions, which is more friendly to developers.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The relevant link:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/ncform/ncform"&gt;ncform&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://ncform.github.io/ncform/ncform-show/schema-gen/index.html"&gt;ncform schema generator&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://ncform.github.io/ncform/ncform-show/playground/index.html"&gt;ncform playground&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://ncform.github.io/ncform/ncform-theme-elementui/index.html"&gt;ncform standard compoments&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Thanks for reading, bye!&lt;/p&gt;




&lt;p&gt;tags: vue, json-schema, form, generator&lt;/p&gt;

</description>
      <category>vue</category>
      <category>javascript</category>
      <category>form</category>
      <category>json</category>
    </item>
    <item>
      <title>Is the React Hooks enough?</title>
      <dc:creator>Daniel.xiao</dc:creator>
      <pubDate>Wed, 16 Oct 2019 03:35:59 +0000</pubDate>
      <link>https://dev.to/danieldx/is-the-react-hooks-enough-3f3a</link>
      <guid>https://dev.to/danieldx/is-the-react-hooks-enough-3f3a</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--EhngGlcQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://ss1.bdstatic.com/70cFvXSh_Q1YnxGkpoWK1HF6hhy/it/u%3D2369947519%2C91440372%26fm%3D15%26gp%3D0.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--EhngGlcQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://ss1.bdstatic.com/70cFvXSh_Q1YnxGkpoWK1HF6hhy/it/u%3D2369947519%2C91440372%26fm%3D15%26gp%3D0.jpg" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Here assumes that you are familiar with Hooks, the new feature on React. &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Now, we are going to talk about whether the &lt;code&gt;useXXX&lt;/code&gt; APIs currently available in React Hooks is sufficient and whether it can meet our daily development needs.&lt;/p&gt;

&lt;h2&gt;
  
  
  First, the most important: State
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;Daniel: Hey, useState is such a core API, isn't it specifically for dealing with state?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Yes, absolutely. Those of you who have used &lt;code&gt;useState&lt;/code&gt; should know that the original &lt;code&gt;this.setstate&lt;/code&gt; can now be replaced by the method &lt;code&gt;setXXX&lt;/code&gt; in the return value of &lt;code&gt;useState&lt;/code&gt;, as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const [ count, setCount ] = useState(0);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's make a simple comparison between &lt;code&gt;class&lt;/code&gt; and &lt;code&gt;Hooks&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# get state

class: this.state.count
Hooks: count

# set state

class: this.setState({count: 1})
Hooks: setCount(1)

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Daniel: That's easy. Anyone who's ever heard of React Hooks knows it. So that's what you're going to tell me?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Of course not. Did you find anything missing? Does the original &lt;code&gt;this.setstate()&lt;/code&gt; has a second parameter? Is this second parameter a callback method? Is this method called after state update successful?&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Daniel: That sounds like something you said, but callback is something I don't use very often. Can you tell me about the scenes used?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Of course, Such as city selector. When you select a province, you need to get the corresponding data of cities, and this moment callback will be used. Let's look at an example of &lt;code&gt;setState&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class App extends React.Component {
  constructor() {
    this.state = {
      pId: 0
    };
  }

  onProvinceChanged(val) {
    this.setState({ pId: val }, () =&amp;gt; {
      fetchCities(this.state.pId);
    });
  }

  ...
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Consider that without callback, it would be harder to do something else exactly after the state update&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Daniel: So React Hooks can't fix it? I don't believe it.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Of course not. This requirement can be achieved by using &lt;code&gt;useEffect&lt;/code&gt;. Let's take a look at how this can be done using the &lt;code&gt;Hooks&lt;/code&gt; approach&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function App() {
  const [pId, setPId] = useState(0);

  useEffect(
    function() {
      fetchCities(pId);
    },
    [pId]
  );

  function onProvinceChanged(val) {
    setPId(val);
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Daniel: So what are you going to say?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If you look at the above codes, they looks like the event pattern, one is listening (useEffect listens for changes in pId and then executes the method) and one is firing the event(setPId).&lt;/p&gt;

&lt;p&gt;The event pattern can act as a decoupling of the code, but it also means that the code is loose, with one side only responsible for triggering events and not caring about what happens next. But our requirements here are very clear, I chose the province, the next is definitely to load the city data, the logic of these two steps is related. So, of course, I hope to be close to the better, so that the code is more organized, read more smoothly, easy to understand.&lt;/p&gt;

&lt;p&gt;Anyway, I feel that I still have to use the callback mode. It’s important to complete the task, but the readability and maintainability of the code are also very important.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Daniel: But didn't you say that useState doesn't provide callback? So what can we do now?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Of course, the official is not currently provided, but we can do it in the way of custom Hooks. &lt;/p&gt;

&lt;p&gt;Now, we will use the third party open source library &lt;a href="https://github.com/daniel-dx/nice-hooks"&gt;nice-hooks&lt;/a&gt; to meet our requirements.&lt;/p&gt;

&lt;p&gt;Rewrite the above example in the way nice-hooks provide, as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { useStateCB } from 'nice-hooks';

function App() {
  const [pId, setPId] = useStateCB(0);

  function onProvinceChanged(val) {
    setPId(val, newPID =&amp;gt; {
      fetchCities(newPID);
    });
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You see, with the return of callback, Hooks are at least as good at handling state as &lt;code&gt;this.setstate&lt;/code&gt; and are not left behind.&lt;/p&gt;

&lt;p&gt;Ok, that's it for Hooks on handling state.&lt;/p&gt;

&lt;p&gt;==== ☕ Suggest taking a break and looking into the distance for a few minutes ==== &lt;/p&gt;

&lt;h2&gt;
  
  
  Next, talk about the life cycle.
&lt;/h2&gt;

&lt;p&gt;As we all know, every component has its life cycle from birth to death. In React, often used are: &lt;code&gt;componentDidMount&lt;/code&gt;, &lt;code&gt;componentDidUpdate&lt;/code&gt;, &lt;code&gt;componentWillUnmount&lt;/code&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Daniel: React Hooks have a lot of corresponding useXXX methods, right?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I think so too, but the reality is that we haven't found an official useXXX method for this. However, we can still implement these lifecycles with the official API currently available. So let's go through them one by one.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;componentDidMount&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This lifecycle method is executed after the component is mounted, and we can use &lt;code&gt;useEffect&lt;/code&gt; to do this. How? Let's do an example&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;useEffect(() =&amp;gt; {
  console.log('Do something, such as fetching data');    
}, [])
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Passing an empty array means that the dependency is invariant, so it only executes once after the first rendering of the component, which is equivalent to componentDidMount&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;componentWillUnmout&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This function is executed when the component is about to be destroyed. Accordingly, we can still use useEffect to achieve this purpose. See the following example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;useEffect(() =&amp;gt; {
  console.log('Do something, such as fetching data');
  return function() {
      console.log('Do something before destroyed')
  }
}, [])
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Since the destroy action is only executed once throughout the life cycle, we can add a return function to the first example that will be executed when the component is destroyed&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;componentDidUpdate&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This function is executed whenever the props, state of the component changes, and you can still use useEffect to achieve this&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;useEffect(() =&amp;gt; {
  console.log('Do something when props / state changes')  
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No dependency values are provided, so they are executed after each rendering, similar to componentDidUpdate.&lt;/p&gt;

&lt;p&gt;But here is a little problem, that is, when it is initialized, it will be executed here too, that is, it will include DidMount. It needs to write some additional code to support it, but I'm not plan to expand it here.&lt;/p&gt;

&lt;p&gt;We can also use &lt;code&gt;useEffect&lt;/code&gt; for the purpose of watching a state or props change. So you will find that the life cycle is mixed in a bunch of &lt;code&gt;useEffect&lt;/code&gt; code, not so straightforward.&lt;/p&gt;

&lt;p&gt;Although &lt;code&gt;useEffect&lt;/code&gt; can implement various lifecycle methods, it is still the problem, the readability and maintainability of the code are important. We can also use the &lt;a href="https://github.com/daniel-dx/nice-hooks"&gt;nice-hooks&lt;/a&gt;. The usage is very simple and the code is clear at a glance.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;useLifeCycle({
  didMount() {
    console.log('Do something, such as fetching data');
  },
  didUpdate() {
    console.log('Do something when props / state changes')   
  },
  willUnmount() {
    console.log('Do something before destroyed')  
  }
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In addition, the life cycle method of the &lt;code&gt;class&lt;/code&gt; component has a small flaw, that is, when you need to destroy some things declared during initialization, such as event listeners, such as timers, registration and destruction logic is forcibly written in different places, easy to neglect and cause a bug, so &lt;code&gt;useLifeCycle&lt;/code&gt; provides a &lt;code&gt;didMountAndWillUnmount&lt;/code&gt; configuration to write the logic in pairs, as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;useLifeCycle({
    didMountAndUnmount: [
      {
          didMount() {
              console.log('register foo event)
          },
          willUnmount() {
              console.log('unregister foo event)
          }
      },
      {
          didMount() {
              console.log('register bar event)
          },
          willUnmount() {
              console.log('unregister bar event)
          }
      }
    ]
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then the recommended practice is to write the paired logic in didMountAndWillUnmount, and others in didMount and willUnmount.&lt;/p&gt;

&lt;p&gt;==== ☕ I suggest you take a break and listen a piece of music ====&lt;/p&gt;

&lt;h2&gt;
  
  
  Finally, let's talk about Instance Variables
&lt;/h2&gt;

&lt;p&gt;When using Hooks to write components, because it is now a pure function component, you can't declare instance variables like &lt;code&gt;class&lt;/code&gt;. The following variable is problematic.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function comp() {
    let name = 'daniel';
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Daniel: The variables declared in the function are normal. Is there a problem?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;You may have modified the value of name somewhere, and expect that when you use the name variable, its value is the last modified value. &lt;/p&gt;

&lt;p&gt;Unfortunately, it is counterproductive, because each time the component is re-rendered, the rendering function will be re-executed, and the variable will be re-initialized.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Daniel: Oh, it seems to be, now there is only one render function left, and it will be re-executed every time. What should we do?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;We can use the official hook &lt;code&gt;useRef&lt;/code&gt;, whose &lt;code&gt;current&lt;/code&gt; attribute will always hold the last value, as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function comp() {
  const nameRef = useRef('daniel');

  function someFn() {
    // get
    let name = nameRef.current;
    // set
    nameRef.current = 'sarah';
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once we have modified the value of the &lt;code&gt;current&lt;/code&gt; property, the &lt;code&gt;current&lt;/code&gt; value will remain the last modified value the next time we re-render, achieving the effect of the instance variable.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Daniel: I guess you will say something, such as the code is not very readable.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Yeah, you are right, the code looks unfriendly.&lt;/p&gt;

&lt;p&gt;It is still recommended to use &lt;a href="https://github.com/daniel-dx/nice-hooks"&gt;nice-hooks&lt;/a&gt;, its &lt;code&gt;useInstanceVar&lt;/code&gt; hook, similar to useState, the difference is that setXXX does not cause re-rendering, just changed the value of the instance variable. The example is as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function comp() {
  const [nameVar, setNameVar] = useInstanceVar('daniel');

  function someFn() {
    // get
    nameVar;
    // set
    setNameVar('sarah');
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It is recommended to use &lt;code&gt;Var&lt;/code&gt; as a suffix to distinguish state when declaring variable names, such as [ xxxVar, setXXXVar ]&lt;/p&gt;

&lt;p&gt;==== Ending dividing line ====&lt;/p&gt;

&lt;p&gt;All of the above are using &lt;a href="https://github.com/daniel-dx/nice-hooks"&gt;nice-hooks&lt;/a&gt;, a third-party open source library to make React Hooks work better.&lt;/p&gt;

&lt;p&gt;If you have some good suggestions, please feel free to submit some issues;&lt;/p&gt;

&lt;p&gt;If you feel that it is useful to you, please add a star to this open source project.&lt;/p&gt;

&lt;p&gt;Thanks for reading!&lt;/p&gt;

</description>
      <category>react</category>
      <category>hooks</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Form generation scheme from a JSON schema</title>
      <dc:creator>Daniel.xiao</dc:creator>
      <pubDate>Wed, 16 Oct 2019 03:33:03 +0000</pubDate>
      <link>https://dev.to/danieldx/form-generation-scheme-from-a-json-schema-2b0e</link>
      <guid>https://dev.to/danieldx/form-generation-scheme-from-a-json-schema-2b0e</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--qxJ611fL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-gold-cdn.xitu.io/2019/3/3/16943deeb66bcd43%3Fw%3D700%26h%3D692%26f%3Dpng%26s%3D139107" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--qxJ611fL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-gold-cdn.xitu.io/2019/3/3/16943deeb66bcd43%3Fw%3D700%26h%3D692%26f%3Dpng%26s%3D139107" alt="banner"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Sarah: "There are a lot of forms for new business system to be developed. Is there a solution that make me to do this task efficiently and happily?"&lt;/p&gt;

&lt;p&gt;Oh, I think, configuration development concept should be more suitable, and the community also has some open source projects of this concept.&lt;/p&gt;

&lt;p&gt;Sarah: "What is the configuration development concept?"&lt;/p&gt;

&lt;p&gt;On, just simply define a JSON configuration data to develop the form.&lt;/p&gt;

&lt;p&gt;Sarah: "Great, I am going to search now."&lt;/p&gt;

&lt;p&gt;After a while...&lt;/p&gt;

&lt;p&gt;Sarah: "There are a lot of them, but which one do I choose?"&lt;/p&gt;

&lt;p&gt;Well, let's talk about the selection of configuration concept form development implementation.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;1. Document&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This is essential, no documentation, who dares to use it?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Live Playground&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;It's best to have a super-intuitive, super-image, super-convenient way to show most or all of the features, which might be like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--uvIiIIA1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-gold-cdn.xitu.io/2019/3/3/16943abe4f959bac%3Fw%3D971%26h%3D524%26f%3Dgif%26s%3D349703" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--uvIiIIA1--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-gold-cdn.xitu.io/2019/3/3/16943abe4f959bac%3Fw%3D971%26h%3D524%26f%3Dgif%26s%3D349703" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Out Of The Box&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;It is best to come with a set of commonly used form controls and validation rules to meet most common scenarios, so you don't have to expand too much on your own.&lt;/p&gt;

&lt;p&gt;For example, the following components are often used:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--sGoESCpe--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-gold-cdn.xitu.io/2019/3/3/169433c41da39d40%3Fw%3D218%26h%3D298%26f%3Dgif%26s%3D56474" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--sGoESCpe--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-gold-cdn.xitu.io/2019/3/3/169433c41da39d40%3Fw%3D218%26h%3D298%26f%3Dgif%26s%3D56474" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For example, the following verification rules are often used:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--YSgg9IGB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-gold-cdn.xitu.io/2019/3/3/169433c41f7d5cf9%3Fw%3D695%26h%3D359%26f%3Dpng%26s%3D93622" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--YSgg9IGB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-gold-cdn.xitu.io/2019/3/3/169433c41f7d5cf9%3Fw%3D695%26h%3D359%26f%3Dpng%26s%3D93622" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Expansion Ability&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;No more components and validation rules can meet all the requirements. So must be &lt;strong&gt;friendly (simple and convenient)&lt;/strong&gt; support developers to customize their own form components and validation rules&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. Support for complex data structures&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A form data structure, in addition to a simple object type with only one level attribute (such as &lt;code&gt;{name: 'daniel', age: 18}&lt;/code&gt;), many actual scenes might look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"firstName"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"daniel"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"lastname"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"xiao"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It might be like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"daniel"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"hobbies"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Coding"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Singing"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Summary: must support for array type, object nested object, object nested array, array items are normal type or object type or array type&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;6. Form Control Interaction&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The form controls are not independent, they interact with each other&lt;/p&gt;

&lt;p&gt;Here are some representative scenes：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;"Agree to continue" type
&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--GRqJHjCq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-gold-cdn.xitu.io/2019/3/3/16943b249d93c1c7%3Fw%3D540%26h%3D275%26f%3Dgif%26s%3D26353" alt="image"&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--FYufBaJO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-gold-cdn.xitu.io/2019/3/3/16943b71f5ce0923%3Fw%3D769%26h%3D286%26f%3Dgif%26s%3D43103" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--FYufBaJO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-gold-cdn.xitu.io/2019/3/3/16943b71f5ce0923%3Fw%3D769%26h%3D286%26f%3Dgif%26s%3D43103" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;"City Selector" type&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--YGhqds6F--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-gold-cdn.xitu.io/2019/3/3/16943b8f8292baf9%3Fw%3D456%26h%3D173%26f%3Dgif%26s%3D78443" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--YGhqds6F--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-gold-cdn.xitu.io/2019/3/3/16943b8f8292baf9%3Fw%3D456%26h%3D173%26f%3Dgif%26s%3D78443" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;"Required filling in when more than 18 years old" type&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--wVJqwqsB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-gold-cdn.xitu.io/2019/3/3/16943cca160441eb%3Fw%3D430%26h%3D218%26f%3Dgif%26s%3D25523" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--wVJqwqsB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-gold-cdn.xitu.io/2019/3/3/16943cca160441eb%3Fw%3D430%26h%3D218%26f%3Dgif%26s%3D25523" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;"Date Comparison" type&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--mjcd8dRa--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-gold-cdn.xitu.io/2019/3/3/16943d27e9c97c7a%3Fw%3D441%26h%3D208%26f%3Dgif%26s%3D56300" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--mjcd8dRa--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-gold-cdn.xitu.io/2019/3/3/16943d27e9c97c7a%3Fw%3D441%26h%3D208%26f%3Dgif%26s%3D56300" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;"Full name autofill" type&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--0oLZkNc9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-gold-cdn.xitu.io/2019/3/3/169433c455b2b873%3Fw%3D432%26h%3D189%26f%3Dgif%26s%3D12875" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--0oLZkNc9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://user-gold-cdn.xitu.io/2019/3/3/169433c455b2b873%3Fw%3D432%26h%3D189%26f%3Dgif%26s%3D12875" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I feel that there are already quite a lot of them. I will not list them one by one.&lt;/p&gt;

&lt;p&gt;So, sarah, if the candidate open source project can meet the above mentioned conditions, then it can be used.&lt;/p&gt;

&lt;p&gt;Sarah: "Oh, do you have a recommendation?"&lt;/p&gt;

&lt;p&gt;Of course. I recommend &lt;strong&gt;ncform&lt;/strong&gt;&lt;/p&gt;




&lt;p&gt;ncform, a nice form development way that generates form UIs and their interactions with just configuration.&lt;/p&gt;

&lt;p&gt;Comes with standard components and validation rules, out of the box.&lt;/p&gt;

&lt;p&gt;Have powerful control interaction and extension capabilities, do what you want.&lt;/p&gt;

&lt;p&gt;Visit the official Github for more information: &lt;a href="https://github.com/ncform/ncform"&gt;https://github.com/ncform/ncform&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;tags: vue, form, generator, json-schema&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>vue</category>
      <category>json</category>
      <category>schema</category>
    </item>
  </channel>
</rss>
