在命令行里也能使用React

用过 React 的同学都知道,React 作为一个视图库,在进行 Web 开发的时候需要安装两个模块。

为滨海新区等地区用户提供了全套网页设计制作服务,及滨海新区网站建设行业解决方案。主营业务为成都做网站、成都网站制作、滨海新区网站设计,以传统方式定制建设网站,并提供域名空间备案等一条龙服务,秉承以专业、用心的态度为用户提供真诚的服务。我们深信只要达到每一位用户的要求,就会得到认可,从而选择与我们长期合作。这样,我们也可以走得更远!

 
 
 
 
  1. npm install react --save
  2. npm install react-dom --save

react 模块主要提供了组件的生命周期、虚拟 DOM Diff、Hooks 等能力,以及将 JSX 转换为虚拟 DOM 的 h 方法。而 react-dom 主要对外暴露一个 render 方法,将虚拟 DOM 转化为真实 DOM。

 
 
 
 
  1. import React from 'react'
  2. import ReactDOM from 'react-dom'
  3. /* import ReactDOM from 'react-dom/server' //服务的渲染 */
  4. class Hello extends React.component {
  5.   render() {
  6.     return 

    Hello, world!

    ,
  7.   }
  8. }
  9. ReactDOM.render(
  10.   ,
  11.   document.getElementById('root')
  12. )

 如果我们将 react-dom 换成 react-native 就可以将虚拟 DOM 转换为安卓或 iOS 的原生组件。我在之前的文章中介绍过,虚拟 DOM 最大的优势并不是其 Diff 算法,而是将 JSX 转换为统一的 DSL,通过其抽象能力实现了跨平台的能力。除了官方提供的 react-dom、react-native ,甚至可以渲染到命令行上,这也是我们今天介绍的 ink。

  •  npm ink: https://www.npmjs.com/package/react-dom

[[413983]] Ink

ink内部使用 facebook 基于 C++ 开发的一款跨平台渲染引擎 yoga,支持 Flex 布局,功能十分强大。另外,React Native 内部使用了该引擎。

初始化

这里有一个官方提供的脚手架,我们可以直接通过这个脚手架来创建一个项目。

 
 
 
 
  1. $ mkdir ink-app
  2. $ cd ink-app
  3. $ npx create-ink-app

如果你想使用 TypeScript 来编写项目,你也可以使用如下命令:

 
 
 
 
  1. $ npx create-ink-app --typescript

生成的代码如下:

 
 
 
 
  1. // src/cli.js
  2. #!/usr/bin/env node
  3. const ink = require('ink')
  4. const meow = require('meow')
  5. const React = require('react')
  6. const importJsx = require('import-jsx')
  7. const ui = importJsx('./ui')
  8. const cli = meow(`
  9.  Usage
  10.    $ ink-cli
  11.  Options
  12.   --name  Your name
  13. `)
  14. ink.render(React.createElement(ui, cli.flags))
 
 
 
 
  1. // src/ui.js
  2. const App = (props) => (
  3.   
  4.     Hello, 
  5.     { props.name || 'UserName' }
  6.    
  7.   
  8. )
  9. module.exports = App;

除了 ink 和 react,脚手架项目还引入了 meow、import-jsx 两个库。

meow 的主要作用是运行命令时,对参数进行解析,将解析的参数放到 flags 属性中,其作用与 yargs、commander 一样,是构建 CLI 工具的必备利器。

 
 
 
 
  1. const meow = require('meow')
  2. // 传入的字符串,作为 help 信息。
  3. const cli = meow(`
  4.  Options
  5.   --name  Your name
  6.   --age   Your age
  7. `)
  8. console.log('flags: ', cli.flags)

另一个 import-jsx 的主要作用,就是将 jsx 字符串转化为 createElement 方法的形式。

 
 
 
 
  1. // ui.js
  2. const component = (props) => (
  3.   
  4.     Hello, 
  5.     { props.name || 'UserName' }
  6.    
  7.   
  8. )
  9. // cli.js
  10. const importJsx = require('import-jsx')
  11. const ui = importJsx('./ui')
  12. console.log(ui.toString()) // 输出转化后的结果
 
 
 
 
  1. // 转化结果:
  2. props => /*#__PURE__*/React.createElement(
  3.   Text,
  4.   null,
  5.   "Hello, ",
  6.   /*#__PURE__*/React.createElement(
  7.     Text, {
  8.       color: "green"
  9.     },
  10.     props.name || 'UserName'
  11.   )
  12. )

这一步的工作一般由 babel 完成,如果我们没有通过 babel 转义 jsx,使用 import-jsx 就相当于是运行时转义,对性能会有损耗。但是,在 CLI 项目中,本身对性能要求也没那么高,通过这种方式,也能更快速的进行项目搭建。

内置组件

由于是非浏览器的运行环境,ink 与 react-native 一样提供了内置的一些组件,用于渲染终端中的特定元素。

组件用于在终端渲染文字,可以为文字指定特定的颜色、加粗、斜体、下划线、删除线等等。

DEMO:

 
 
 
 
  1. // ui.js
  2. const React = require('react')
  3. const { Text } = require('ink')
  4. moudle.exports = () => (<>
  5.   I am text
  6.   I am bold
  7.   I am italic
  8.   I am underline
  9.   I am strikethrough
  10.   I am green
  11.   I am blue on gray
  12. )
  13. // cli.js
  14. const React = require('react')
  15. const importJsx = require('import-jsx')
  16. const { render } = require('ink')
  17. const ui = importJsx('./ui')
  18. render(React.createElement(ui))

其主要作用就是设置渲染到终端上的文本样式,有点类似于 HTML 中的 标签。

除了这种常见的 HTML 相关的文本属性,还支持比较特殊的 wrap 属性,用于将溢出的文本进行截断。

长文本在超出终端的长度时,默认会进行换行处理。

 
 
 
 
  1. loooooooooooooooooooooooooooooooooooooooong text

如果加上 wrap 属性,会对长文本进行截断。

 
 
 
 
  1.   loooooooooooooooooooooooooooooooooooooooong text

除了从尾部截断文本,还支持从文本中间和文本开始处进行截断。

 
 
 
 
  1.   loooooooooooooooooooooooooooooooooooooooong text
  2.   loooooooooooooooooooooooooooooooooooooooong text
  3.   loooooooooooooooooooooooooooooooooooooooong text

组件用于布局,除了支持类似 CSS 中 margin、padding、border 属性外,还能支持 flex 布局,可以将 理解为 HTML 中设置了 flex 布局的 div (

)。

下面我们先给一个 组件设置高度为 10,然后主轴方向让元素两端对齐,交叉轴方向让元素位于底部对齐。

然后在给内部的两个 组件设置一个 padding 和一个不同样式的边框。

 
 
 
 
  1. const App = () => 
  2.   height={10}
  3.   alignItems="flex-end"
  4.   justifyContent="space-between"
  5. >
  6.  
  7.     Hello
  8.   
  9.  
  10.    World
  11.   

最终效果如下:

比较特殊的属性是边框的样式:borderStyle,和 CSS 提供的边框样式有点出入。

 
 
 
 
  1.   single
  2.   double
  3.   round
  4.   bold
  5.   singleDouble
  6.   doubleSingle
  7.   classic

组件提供的其他属性和原生的 CSS 基本一致,详细介绍可以查阅其文档:

  • ink#Box:https://www.npmjs.com/package/ink#box

组件相当于直接在终端中添加一个 \n 字符,用于换行(PS:只支持插入在 元素之间);

 
 
 
 
  1. const App = () => (<>
  2.   Hello
  3.   World
  4. )

 
 
 
 
  1. const App = () => (<>
  2.   Hello
  3.   
  4.   World
  5. )

组件用于隔开两个元素,使用后,会将间隔开两个元素隔开到终端的两边,效果有点类似于 flex 布局的两端对齐(justify-content: space-between;)

 
 
 
 
  1. const App1 = () => 
  2.   Left
  3.   
  4.   Right
  5. ;
  6. const App2 = () => 
  7.   Left
  8.   Right
  9. ;

上面两段代码的表现形式一致:

内置 Hooks

ink 除了提供一些布局用的组件,还提供了一些 Hooks。

useInput

可用于监听用户的输入,useInput 接受一个回调函数,用户每次按下键盘的按键,都会调用 useInput 传入的回调,并传入两个参数。

 
 
 
 
  1. useInput((input: string, key: Object) => void)

第一个参数:input ,表示按下按键对应的字符。第二个参数:key ,为一个对象,对应按下的一些功能键。

  • 如果按下回车,key.return = true;
  • 如果按下删除键,key.delete = true;
  • 如果按下esc键,key.escape = true;

具体支持哪些功能按键,可以参考官方文档:

  • ink#useInput:https://www.npmjs.com/package/ink#useinputinputhandler-options

下面通过一个 DEMO,展示其具体的使用方式,在终端上记录用户的所有输出,如果按下的是删除键,则删除最近记录的一个字符。

 
 
 
 
  1. const React = require('react')
  2. const { useInput, Text } = require('ink')
  3. const { useState } = React
  4. module.exports = () => {
  5.   const [char, setChar] = useState('')
  6.   useInput((input, key) => {
  7.     if (key.delete) {
  8.       // 按下删除键,删除一个字符
  9.       setChar(char.slice(0, -1))
  10.       return
  11.     }
  12.     // 追加最新按下的字符
  13.     setChar(char + input)
  14.   })
  15.   return input char: {char}
  16. }

useApp

对外暴露一个 exit 方法,用于退出终端。

 
 
 
 
  1. const React = require('react')
  2. const { useApp } = require('ink')
  3. const { useEffect } = React
  4. const App = () => {
  5.   const { exit } = useApp()
  6.  // 3s 后退出终端
  7.  useEffect(() => {
  8.   setTimeout(() => {
  9.    exit();
  10.   }, 3000);
  11.  }, []);
  12.  return 3s 后退出终端……
  13. }

useStdin

用于获取命令行的输入流。这里用一个简单的案例,来模拟用户登录。

 
 
 
 
  1. const React = require('react')
  2. const { useStdin } = require('ink')
  3. const { useState, useEffect } = React
  4. module.exports = () => {
  5.   const [pwd, setPwd] = useState('')
  6.   const { stdin } = useStdin()
  7.   
  8.   useEffect(() => {
  9.     // 设置密码后,终止输入
  10.     if (pwd) stdin.pause()
  11.  }, [pwd])
  12.   
  13.   stdin.on('data', (data) => {
  14.     // 提取 data,设置到 pwd 变量中
  15.     const value = data.toString().trim()
  16.     setPwd(value)
  17.   })
  18.   // pwd 为空时,提示用户输入密码
  19.   if (!pwd) {
  20.     return password:
  21.   }
  22.   return pwd === 'hk01810'
  23.     ? 登录成功
  24.     : 有内鬼,终止交易
  25. }

useStdout

用于获取命令行的输出流。会暴露 stdout 的写入流,还会暴露一个 write 方法,用于在终端进行输入。

 
 
 
 
  1. const React = require('react')
  2. const { useStdout } = require('ink')
  3. const { useEffect } = React
  4. module.exports = () => {
  5.   const { write } = useStdout()
  6.   useEffect(() => {
  7.     // 在终端进行写入
  8.   write('Hello from Ink to stdout')
  9.  }, [])
  10.   return null
  11. }

第三方组件

除了内置的这些组件和 Hooks 外,还有丰富的第三方生态。比如:Loading组件、超链接组件、表格组件、高亮组件、多选组件、图片组件……

  • ink#第三方组件:https://www.npmjs.com/package/ink#useful-components

ink-spinner

ink-link

ink-table

ink-syntax-highlight

ink-muti-select

调试工具

ink 属于 React 生态,自然能够支持 React 官方提供的调试工具 React Devtools。

 
 
 
 
  1. $ npm install react-devtools # 安装调试工具
 
 
 
 
  1. $ npx react-devtools # 启动调试工具

然后,在启动应用时,在前面设置 DEV 全局变量。

 
 
 
 
  1. DEV=true node src/cli

运行后的效果如下:

总结

React 确实是视图开发的一把利器,再加上 Hooks 的加持,其抽象能力得到了进一步的提升,统一的 DSL 加上 虚拟 DOM,照理来说,是可以在任何平台进行渲染的。甚至,微软官方都开发了一个 React Native for Windows,关键是这个东西不仅仅能开发 Windows 的桌面软件,还可以开发 mac 的桌面软件。

有点跑题,说回 ink,大家熟知的 Gatsby 的命令行工具也是通过 ink 进行开发的。如果大家后续有本地的 CLI 工具需要实现,可以考虑这款工具,至少不必烦恼如何在命令行进行文本对齐。

网站标题:在命令行里也能使用React
网页URL:http://www.shufengxianlan.com/qtweb/news16/101266.html

网站建设、网络推广公司-创新互联,是专注品牌与效果的网站制作,网络营销seo公司;服务项目有等

广告

声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 创新互联