国产精品电影_久久视频免费_欧美日韩国产激情_成年人视频免费在线播放_日本久久亚洲电影_久久都是精品_66av99_九色精品美女在线_蜜臀a∨国产成人精品_冲田杏梨av在线_欧美精品在线一区二区三区_麻豆mv在线看

在命令行里也能使用 React

開發 前端
React 確實是視圖開發的一把利器,再加上 Hooks 的加持,其抽象能力得到了進一步的提升,統一的 DSL 加上 虛擬 DOM,照理來說,是可以在任何平臺進行渲染的。

[[413982]]

用過 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

[[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.  
  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) 

另一個 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 中的 標簽

除了這種常見的 HTML 相關的文本屬性,還支持比較特殊的 wrap 屬性,用于將溢出的文本進行截斷。

長文本在超出終端的長度時,默認會進行換行處理。

  1. <Text>loooooooooooooooooooooooooooooooooooooooong text</Text> 

如果加上 wrap 屬性,會對長文本進行截斷。

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

除了從尾部截斷文本,還支持從文本中間和文本開始處進行截斷。

  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> 

<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> 

最終效果如下:

比較特殊的屬性是邊框的樣式: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> 

<Box> 組件提供的其他屬性和原生的 CSS 基本一致,詳細介紹可以查閱其文檔:

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

<Newline>

<NewLine> 組件相當于直接在終端中添加一個 \n 字符,用于換行(PS:只支持插入在 <Text> 元素之間);

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

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

<Spacer>

<Spacer> 組件用于隔開兩個元素,使用后,會將間隔開兩個元素隔開到終端的兩邊,效果有點類似于 flex 布局的兩端對齊(justify-content: space-between;)

  1. const App1 = () => <Box> 
  2.   <Text>Left</Text> 
  3.   <Spacer /> 
  4.   <Text>Right</Text> 
  5. </Box>; 
  6.  
  7. const App2 = () => <Box justifyContent="space-between"
  8.   <Text>Left</Text> 
  9.   <Text>Right</Text> 
  10. </Box>; 

上面兩段代碼的表現形式一致:

內置 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.  
  4. const { useState } = React 
  5. module.exports = () => { 
  6.   const [char, setChar] = useState(''
  7.   useInput((input, key) => { 
  8.     if (key.delete) { 
  9.       // 按下刪除鍵,刪除一個字符 
  10.       setChar(char.slice(0, -1)) 
  11.       return 
  12.     } 
  13.     // 追加最新按下的字符 
  14.     setChar(char + input) 
  15.   }) 
  16.   return <Text>input char: {char}</Text> 

useApp

對外暴露一個 exit 方法,用于退出終端。

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

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 <Text backgroundColor="blue">password:</Text> 
  21.   } 
  22.  
  23.   return pwd === 'hk01810' 
  24.     ? <Text color="green">登錄成功</Text> 
  25.     : <Text color="red">有內鬼,終止交易</Text> 

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 

第三方組件

除了內置的這些組件和 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 工具需要實現,可以考慮這款工具,至少不必煩惱如何在命令行進行文本對齊。

 

責任編輯:姜華 來源: 自然醒的筆記本
相關推薦

2019-05-21 10:38:17

Linux命令行

2018-04-15 21:19:30

Linux命令行Wi-Fi

2020-09-09 07:48:42

Linux 命令行通信

2023-03-08 15:38:56

Linux命令dict

2021-07-29 10:00:43

XMLXMLStarletLinux

2018-11-05 13:50:44

Linux命令tcpdump

2023-03-28 08:40:22

命令行JSON用法

2022-10-18 10:00:09

Linuxtcpdump命令

2013-06-08 10:36:47

Linux命令行

2021-03-01 11:16:08

React 前端組件開源

2010-10-12 17:01:21

MySQL命令行

2014-01-24 09:09:32

Linux命令行網速

2010-06-01 19:14:53

SVN命令行

2019-12-09 09:23:04

Linux命令sort

2021-07-15 13:32:12

Linux生成密碼

2021-07-15 13:25:43

LinuxPDF

2022-08-14 19:19:14

Linux

2014-01-22 10:21:55

Linux命令行

2009-08-16 20:24:59

linux命令行登陸linux命令行linux命令

2020-12-11 06:44:16

命令行工具開發
點贊
收藏

51CTO技術棧公眾號

日韩av中文字幕一区二区三区| 日本高清在线观看| 日本精品在线一区| www.av蜜桃| videoxxxx另类日本极品| 17c丨国产丨精品视频| 最近免费观看高清韩国日本大全| 高清在线视频不卡| 久久免费看少妇高潮| 午夜先锋成人动漫在线| 97久久亚洲| 久久久精品人体av艺术| 97视频在线看| 日本在线丨区| 成人动漫视频在线| 一区二区三区欧美| 国产91在线播放| 国产精品亚洲欧美一级在线 | 日本乱人伦一区| 国产精品av免费| 国产深夜男女无套内射| 欧美男男freegayvideosroom| 中文字幕综合| 日韩高清影视在线观看| 粉嫩老牛aⅴ一区二区三区| 国产免费毛卡片| av之家在线观看| 美女搞黄视频在线观看| 亚洲精品国产高清久久伦理二区| 午夜欧美不卡精品aaaaa| 黄色成人影院| 久久综合久久综合亚洲| 成人av影视在线| 欧美精品一区二区视频| 亚洲视频一二| 精品视频一区二区| 国产在线你懂得| 一级毛片免费观看| 日韩高清不卡在线| 欧美成人国产一区二区| 亚洲xxxx做受欧美| 里番在线观看网站| 欧美视频一区二| 成人影院在线看| 日韩一区二区在线观看视频| 91xxx在线观看| 欧美二区在线观看| 日韩精品免费一区二区夜夜嗨| 国产成人福利视频| 亚洲成人1区| 久久97超碰色| 亚洲观看高清完整版在线观看 | 国产精品免费视频观看| 欧美一级黄色片| 国产剧情av在线| 亚洲中国最大av网站| www.爱色av.com| 一道本在线观看视频| 亚洲乱码电影| 一级黄色免费在线观看| 国产成人亚洲综合a∨婷婷| 欧美午夜精品久久久久免费视 | 亚洲欧洲日韩综合二区| 久久99国产精品久久99果冻传媒| 麻豆久久久av免费| 国模少妇一区二区三区| 亚洲一区二区三区成人| 精品国产欧美日韩一区二区三区| 色妞色视频一区二区三区四区| 国内精品久久久久影院优| 丝袜+亚洲+另类+欧美+变态| 国产精一品亚洲二区在线视频| 在线观看免费国产小视频| 成人午夜视频免费看| 国产白丝精品91爽爽久久 | 日韩中文字幕在线观看| 岛国av在线播放| caoporn视频在线| 成人97在线观看视频| 日韩欧美视频在线播放| 亚洲欧美经典视频| 欧美jizzhd69巨大| 中文字幕亚洲欧美| 亚洲精品久久久蜜桃| 青青草原av在线| 一区二区三区韩国免费中文网站| 99热在线播放| 免费免费啪视频在线观看| 久久在精品线影院精品国产| 精品久久国产| 天堂а√在线资源在线| 亚洲欧洲午夜一线一品| 中文字幕一区二区三区四区久久| 91精品国产综合久久久久久漫画 | 久久国产精品首页| 欧美顶级大胆免费视频| 麻豆国产欧美一区二区三区| 欧美精品久久久久久久久久久| 亚洲欧美在线视频| 秋霞久久久久久一区二区| 91蜜桃免费观看视频| 加勒比一区二区三区在线| 九九久久久久99精品| 夜夜精品视频| jizzjizz亚洲中国少妇| 亚洲精品视频播放| 国产亚洲一区在线| 91黑丝在线| 国产精品网站在线播放| 国产欧美黑人| 欧美一区二三区| 久久国产精品第一页| 亚洲欧美另类人妖| 理论电影国产精品| 性色av一区二区三区| 久久亚洲国产精品一区二区| 日本在线观看免费视频| 日韩欧美黄色影院| 色999日韩| 欧美色图另类小说| 精品精品国产高清一毛片一天堂| 婷婷五月色综合香五月| 免费cad大片在线观看| 色婷婷av一区二区三区gif| 日韩精品一区二区三区中文| 欧美一级黄色大片| 精品中国亚洲| **欧美大码日韩| 韩国精品一区| 国产在线视频欧美一区二区三区| 国产一区二区三区免费观看| 久久久久免费网| 国产精品久久久久一区| 在线手机中文字幕| 日韩福利影院| 在线亚洲精品福利网址导航| 色老板在线视频一区二区| 日韩极品视频在线观看| 精品日韩99亚洲| 亚洲三级影院| 水莓100在线视频| 国产精品日韩精品| 一区二区三区免费看视频| 好吊妞视频这里有精品| 欧美日韩国产精品激情在线播放| 精品欧美黑人一区二区三区| 六月婷婷色综合| 日本在线观看大片免费视频| 国产亚洲一区二区三区在线播放 | 国产综合久久久久久鬼色 | 蜜桃传媒av| 欧美丰满片xxx777| 91视频免费看| 精品一区二区三区免费看| 国产深夜男女无套内射| 一区二区欧美激情| 成人激情午夜影院| 成人在线视频观看| 国产亚洲人成网站在线观看| 亚洲永久免费精品| 淫片在线观看| 欧美日韩一区二区三区在线视频 | 成人av高清在线| 成人黄色免费短视频| 色偷偷av亚洲男人的天堂| 日韩天堂在线观看| 欧美在线日韩| 爱看av在线| 亚洲午夜精品国产| 91在线精品一区二区| 日韩欧美少妇| 欧美日韩亚洲一二三| 久久久之久亚州精品露出| 中文字幕一区二区三区色视频| 精品五月天堂| 在线欧美一级视频| 国产伦精品一区二区三区免费视频| 91激情五月电影| 免费在线观看成人| 亚洲成人av一区| 希岛爱理一区二区三区| 二区在线观看| 日韩尤物视频| 亚洲一级一级97网| 欧美国产日韩a欧美在线观看| 欧美91在线| 国产毛片av在线| 中国成人在线视频| 久久全球大尺度高清视频| 天天色综合天天| 日韩电影在线一区二区三区| 黄色大片在线| 午夜肉伦伦影院| 国产99视频在线观看| 色综合视频在线观看| 国产成人av| 婷婷在线视频| 蜜臀在线免费观看| 国产精品视频自在线| 日韩美一区二区三区|