日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問(wèn)題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷(xiāo)解決方案
在命令行里也能使用React

用過(guò) React 的同學(xué)都知道,React 作為一個(gè)視圖庫(kù),在進(jìn)行 Web 開(kāi)發(fā)的時(shí)候需要安裝兩個(gè)模塊。

為濱海新區(qū)等地區(qū)用戶提供了全套網(wǎng)頁(yè)設(shè)計(jì)制作服務(wù),及濱海新區(qū)網(wǎng)站建設(shè)行業(yè)解決方案。主營(yíng)業(yè)務(wù)為成都做網(wǎng)站、成都網(wǎng)站制作、濱海新區(qū)網(wǎng)站設(shè)計(jì),以傳統(tǒng)方式定制建設(shè)網(wǎng)站,并提供域名空間備案等一條龍服務(wù),秉承以專(zhuān)業(yè)、用心的態(tài)度為用戶提供真誠(chéng)的服務(wù)。我們深信只要達(dá)到每一位用戶的要求,就會(huì)得到認(rèn)可,從而選擇與我們長(zhǎng)期合作。這樣,我們也可以走得更遠(yuǎn)!

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

react 模塊主要提供了組件的生命周期、虛擬 DOM Diff、Hooks 等能力,以及將 JSX 轉(zhuǎn)換為虛擬 DOM 的 h 方法。而 react-dom 主要對(duì)外暴露一個(gè) render 方法,將虛擬 DOM 轉(zhuǎn)化為真實(shí) DOM。

 
 
 
 
  1. import React from 'react'
  2. import ReactDOM from 'react-dom'
  3. /* import ReactDOM from 'react-dom/server' //服務(wù)的渲染 */
  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 轉(zhuǎn)換為安卓或 iOS 的原生組件。我在之前的文章中介紹過(guò),虛擬 DOM 最大的優(yōu)勢(shì)并不是其 Diff 算法,而是將 JSX 轉(zhuǎn)換為統(tǒng)一的 DSL,通過(guò)其抽象能力實(shí)現(xiàn)了跨平臺(tái)的能力。除了官方提供的 react-dom、react-native ,甚至可以渲染到命令行上,這也是我們今天介紹的 ink。

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

[[413983]] Ink

ink內(nèi)部使用 facebook 基于 C++ 開(kāi)發(fā)的一款跨平臺(tái)渲染引擎 yoga,支持 Flex 布局,功能十分強(qiáng)大。另外,React Native 內(nèi)部使用了該引擎。

初始化

這里有一個(gè)官方提供的腳手架,我們可以直接通過(guò)這個(gè)腳手架來(lái)創(chuàng)建一個(gè)項(xiàng)目。

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

如果你想使用 TypeScript 來(lái)編寫(xiě)項(xiàng)目,你也可以使用如下命令:

 
 
 
 
  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,腳手架項(xiàng)目還引入了 meow、import-jsx 兩個(gè)庫(kù)。

meow 的主要作用是運(yùn)行命令時(shí),對(duì)參數(shù)進(jìn)行解析,將解析的參數(shù)放到 flags 屬性中,其作用與 yargs、commander 一樣,是構(gòu)建 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)

另一個(gè) import-jsx 的主要作用,就是將 jsx 字符串轉(zhuǎn)化為 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()) // 輸出轉(zhuǎn)化后的結(jié)果
 
 
 
 
  1. // 轉(zhuǎn)化結(jié)果:
  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 完成,如果我們沒(méi)有通過(guò) babel 轉(zhuǎn)義 jsx,使用 import-jsx 就相當(dāng)于是運(yùn)行時(shí)轉(zhuǎn)義,對(duì)性能會(huì)有損耗。但是,在 CLI 項(xiàng)目中,本身對(duì)性能要求也沒(méi)那么高,通過(guò)這種方式,也能更快速的進(jìn)行項(xiàng)目搭建。

內(nèi)置組件

由于是非瀏覽器的運(yùn)行環(huán)境,ink 與 react-native 一樣提供了內(nèi)置的一些組件,用于渲染終端中的特定元素。

組件用于在終端渲染文字,可以為文字指定特定的顏色、加粗、斜體、下劃線、刪除線等等。

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

其主要作用就是設(shè)置渲染到終端上的文本樣式,有點(diǎn)類(lèi)似于 HTML 中的 標(biāo)簽。

除了這種常見(jiàn)的 HTML 相關(guān)的文本屬性,還支持比較特殊的 wrap 屬性,用于將溢出的文本進(jìn)行截?cái)唷?/p>

長(zhǎng)文本在超出終端的長(zhǎng)度時(shí),默認(rèn)會(huì)進(jìn)行換行處理。

 
 
 
 
  1. loooooooooooooooooooooooooooooooooooooooong text

如果加上 wrap 屬性,會(huì)對(duì)長(zhǎng)文本進(jìn)行截?cái)唷?/p>

 
 
 
 
  1.   loooooooooooooooooooooooooooooooooooooooong text

除了從尾部截?cái)辔谋?,還支持從文本中間和文本開(kāi)始處進(jìn)行截?cái)唷?/p>

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

組件用于布局,除了支持類(lèi)似 CSS 中 margin、padding、border 屬性外,還能支持 flex 布局,可以將 理解為 HTML 中設(shè)置了 flex 布局的 div (

)。

下面我們先給一個(gè) 組件設(shè)置高度為 10,然后主軸方向讓元素兩端對(duì)齊,交叉軸方向讓元素位于底部對(duì)齊。

然后在給內(nèi)部的兩個(gè) 組件設(shè)置一個(gè) padding 和一個(gè)不同樣式的邊框。

 
 
 
 
  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 提供的邊框樣式有點(diǎn)出入。

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

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

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

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

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

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

組件用于隔開(kāi)兩個(gè)元素,使用后,會(huì)將間隔開(kāi)兩個(gè)元素隔開(kāi)到終端的兩邊,效果有點(diǎn)類(lèi)似于 flex 布局的兩端對(duì)齊(justify-content: space-between;)

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

上面兩段代碼的表現(xiàn)形式一致:

內(nèi)置 Hooks

ink 除了提供一些布局用的組件,還提供了一些 Hooks。

useInput

可用于監(jiān)聽(tīng)用戶的輸入,useInput 接受一個(gè)回調(diào)函數(shù),用戶每次按下鍵盤(pán)的按鍵,都會(huì)調(diào)用 useInput 傳入的回調(diào),并傳入兩個(gè)參數(shù)。

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

第一個(gè)參數(shù):input ,表示按下按鍵對(duì)應(yīng)的字符。第二個(gè)參數(shù):key ,為一個(gè)對(duì)象,對(duì)應(yīng)按下的一些功能鍵。

  • 如果按下回車(chē),key.return = true;
  • 如果按下刪除鍵,key.delete = true;
  • 如果按下esc鍵,key.escape = true;

具體支持哪些功能按鍵,可以參考官方文檔:

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

下面通過(guò)一個(gè) DEMO,展示其具體的使用方式,在終端上記錄用戶的所有輸出,如果按下的是刪除鍵,則刪除最近記錄的一個(gè)字符。

 
 
 
 
  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.       // 按下刪除鍵,刪除一個(gè)字符
  9.       setChar(char.slice(0, -1))
  10.       return
  11.     }
  12.     // 追加最新按下的字符
  13.     setChar(char + input)
  14.   })
  15.   return input char: {char}
  16. }

useApp

對(duì)外暴露一個(gè) 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

用于獲取命令行的輸入流。這里用一個(gè)簡(jiǎn)單的案例,來(lái)模擬用戶登錄。

 
 
 
 
  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.     // 設(shè)置密碼后,終止輸入
  10.     if (pwd) stdin.pause()
  11.  }, [pwd])
  12.   
  13.   stdin.on('data', (data) => {
  14.     // 提取 data,設(shè)置到 pwd 變量中
  15.     const value = data.toString().trim()
  16.     setPwd(value)
  17.   })
  18.   // pwd 為空時(shí),提示用戶輸入密碼
  19.   if (!pwd) {
  20.     return password:
  21.   }
  22.   return pwd === 'hk01810'
  23.     ? 登錄成功
  24.     : 有內(nèi)鬼,終止交易
  25. }

useStdout

用于獲取命令行的輸出流。會(huì)暴露 stdout 的寫(xiě)入流,還會(huì)暴露一個(gè) write 方法,用于在終端進(jìn)行輸入。

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

第三方組件

除了內(nèi)置的這些組件和 Hooks 外,還有豐富的第三方生態(tài)。比如:Loading組件、超鏈接組件、表格組件、高亮組件、多選組件、圖片組件……

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

ink-spinner

ink-link

ink-table

ink-syntax-highlight

ink-muti-select

調(diào)試工具

ink 屬于 React 生態(tài),自然能夠支持 React 官方提供的調(diào)試工具 React Devtools。

 
 
 
 
  1. $ npm install react-devtools # 安裝調(diào)試工具
 
 
 
 
  1. $ npx react-devtools # 啟動(dòng)調(diào)試工具

然后,在啟動(dòng)應(yīng)用時(shí),在前面設(shè)置 DEV 全局變量。

 
 
 
 
  1. DEV=true node src/cli

運(yùn)行后的效果如下:

總結(jié)

React 確實(shí)是視圖開(kāi)發(fā)的一把利器,再加上 Hooks 的加持,其抽象能力得到了進(jìn)一步的提升,統(tǒng)一的 DSL 加上 虛擬 DOM,照理來(lái)說(shuō),是可以在任何平臺(tái)進(jìn)行渲染的。甚至,微軟官方都開(kāi)發(fā)了一個(gè) React Native for Windows,關(guān)鍵是這個(gè)東西不僅僅能開(kāi)發(fā) Windows 的桌面軟件,還可以開(kāi)發(fā) mac 的桌面軟件。

有點(diǎn)跑題,說(shuō)回 ink,大家熟知的 Gatsby 的命令行工具也是通過(guò) ink 進(jìn)行開(kāi)發(fā)的。如果大家后續(xù)有本地的 CLI 工具需要實(shí)現(xiàn),可以考慮這款工具,至少不必?zé)廊绾卧诿钚羞M(jìn)行文本對(duì)齊。


網(wǎng)頁(yè)題目:在命令行里也能使用React
分享鏈接:http://m.5511xx.com/article/djshsso.html