服务器之家:专注于服务器技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - 编程技术 - 在命令行里也能使用 React

在命令行里也能使用 React

2021-07-29 23:22自然醒的笔记本写文章的自然醒 编程技术

React 确实是视图开发的一把利器,再加上 Hooks 的加持,其抽象能力得到了进一步的提升,统一的 DSL 加上 虚拟 DOM,照理来说,是可以在任何平台进行渲染的。

在命令行里也能使用 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.  
  5. class Hello extends React.component { 
  6.   render() { 
  7.     return <h1>Hello, world!</h1>, 
  8.   } 
  9.  
  10. ReactDOM.render( 
  11.   <Hello />, 
  12.   document.getElementById('root'

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

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

在命令行里也能使用 React 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.  
  8. const ui = importJsx('./ui'
  9.  
  10. const cli = meow(` 
  11.  Usage 
  12.    $ ink-cli 
  13.  Options 
  14.   --name  Your name 
  15. `) 
  16.  
  17. ink.render(React.createElement(ui, cli.flags)) 
  1. // src/ui.js 
  2. const App = (props) => ( 
  3.   <Text> 
  4.     Hello, <Text color = "green"
  5.     { props.name || 'UserName' } 
  6.    </Text> 
  7.   </Text> 
  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) 
在命令行里也能使用 React

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

  1. // ui.js 
  2. const component = (props) => ( 
  3.   <Text> 
  4.     Hello, <Text color = "green"
  5.     { props.name || 'UserName' } 
  6.    </Text> 
  7.   </Text> 
  8.  
  9. // cli.js 
  10. const importJsx = require('import-jsx'
  11. const ui = importJsx('./ui'
  12.  
  13. 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.   ) 

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

内置组件

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

<Text>

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

DEMO:

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

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

在命令行里也能使用 React

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

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

  1. <Text>loooooooooooooooooooooooooooooooooooooooong text</Text> 

在命令行里也能使用 React

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

  1. <Text wrap="truncate"
  2.   loooooooooooooooooooooooooooooooooooooooong text 
  3. </Text> 

在命令行里也能使用 React

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

  1. <Text wrap="truncate"
  2.   loooooooooooooooooooooooooooooooooooooooong text 
  3. </Text> 
  4. <Text wrap="truncate-middle"
  5.   loooooooooooooooooooooooooooooooooooooooong text 
  6. </Text> 
  7. <Text wrap="truncate-start"
  8.   loooooooooooooooooooooooooooooooooooooooong text 
  9. </Text> 

在命令行里也能使用 React

<Box>

<Box> 组件用于布局,除了支持类似 CSS 中 margin、padding、border 属性外,还能支持 flex 布局,可以将 <Box> 理解为 HTML 中设置了 flex 布局的 div ( <div style="display: flex;">)。

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

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

  1. const App = () => <Box 
  2.   height={10} 
  3.   alignItems="flex-end" 
  4.   justifyContent="space-between" 
  5.  <Box borderStyle="double" borderColor="blue" padding={1} > 
  6.     <Text>Hello</Text> 
  7.   </Box> 
  8.  <Box borderStyle="classic"  borderColor="red" padding={1} > 
  9.    <Text>World</Text> 
  10.   </Box> 
  11. </Box> 

最终效果如下:

在命令行里也能使用 React

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

  1. <Box borderStyle="single"
  2.   <Text>single</Text> 
  3. </Box> 
  4. <Box borderStyle="double"
  5.   <Text>double</Text> 
  6. </Box> 
  7. <Box borderStyle="round"
  8.   <Text>round</Text> 
  9. </Box> 
  10. <Box borderStyle="bold"
  11.   <Text>bold</Text> 
  12. </Box> 
  13. <Box borderStyle="singleDouble"
  14.   <Text>singleDouble</Text> 
  15. </Box> 
  16. <Box borderStyle="doubleSingle"
  17.   <Text>doubleSingle</Text> 
  18. </Box> 
  19. <Box borderStyle="classic"
  20.   <Text>classic</Text> 
  21. </Box> 

在命令行里也能使用 React

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

延伸 · 阅读

精彩推荐