头图

使用Vue.js编写命令行界面,前端开发CLI的利器

前言

大家好,我是webfansplz.继将 Vue 渲染到嵌入式液晶屏后,今天要跟大家分享的是如何将Vue渲染到命令行工具 :).关于命令行工具,大家应该都比较熟悉了,比如vue-cli、Vite等.我们在编写前端应用面向用户时,通常会非常关注用户体验,作为开发者,我们在使用工具时,它给予我们的开发者体验(DX)我们也会十分关注. 现代前端工程化离不开CLI的开发与使用、那么是否能有较低成本的方案能让前端小伙伴快速开发CLI,大家可以像编写前端应用一样搞定它.因此,Temir应运而生.

Temir

介绍

Temir,一个用Vue组件来编写命令行界面应用的工具.开发者只需要使用Vue就可以编写命令行应用,不需要任何额外的学习成本.

<script lang="ts" setup>
import { ref } from '@vue/runtime-core'
import { TBox, TText } from '@temir/core'
const counter = ref(0)
setInterval(() => {
  counter.value++
}, 100)
</script>

<template>
  <TBox>
    <TText color="green">
      {{ counter }} tests passed
    </TText>
  </TBox>
</template>

组件

Temir提供了一些基础组件帮助开发者编写与扩展命令行工具:

文本组件 (Text)

文本组件可以显示文本,将其样式更改为粗体、下划线、斜体或删除线.

<TText color="green">
  I am green
</TText>

<TText color="black" background-color="white">
  I am black on white
</TText>

<TText color="white">
  I am white
</TText>

<TText :bold="true">
  I am bold
</TText>

<TText :italic="true">
  I am italic
</TText>

<TText :underline="true">
  I am underline
</TText>

<TText :strikethrough="true">
  I am strikethrough
</TText>

<TText :inverse="true">
  I am inversed
</TText>

盒子组件 (Box)

<Box>是构建布局必不可少的Temir组件.就像在浏览器中<div style='display: flex'>.它提供了一些构建布局的常用属性,比如尺寸、内外边距、对齐方式等.

<template>
  <TBox justify-content="flex-start">
    <TText>X</TText>
  </TBox>
  // [X      ]

  <TBox justify-content="center">
    <TText>X</TText>
  </TBox>
  // [   X   ]

  <TBox justify-content="flex-end">
    <TText>X</TText>
  </TBox>
  // [      X]

  <TBox justify-content="space-between">
    <TText>X</TText>
    <TText>Y</TText>
  </TBox>
  // [X      Y]

  <TBox justify-content="space-around">
    <TText>X</TText>
    <TText>Y</TText>
  </TBox>
  // [  X   Y  ]
</template>

换行组件 (Newline)

添加一个或多个换行符(\n)。 必须在<Text>组件中使用。

<script>
import { TBox, TNewline, TText } from '@temir/core'
</script>

<template>
  <TBox>
    <TText>
      <TText color="green">
        Hello
      </TText>
      <TNewline />
      <TText color="red">
        World
      </TText>
    </TText>
  </TBox>
</template>

填充组件 (Spacer)

沿其包含布局的主轴展开的灵活空间。 作为填充元素之间所有可用空间的快捷方式,它非常有用。

例如,在具有默认伸缩方向(row)的<Box>中使用<Spacer>将把"Left"定位到左边,并将"Right"推到右边。

<script lang="ts" setup>
import { TBox, TSpacer, TText } from '@temir/core'
</script>

<template>
  <TBox>
    <TText>Left</TText>
    <TSpacer />
    <TText>Right</TText>
  </TBox>
</template>

超链接组件 (Link)

<script lang="ts" setup>
import { TBox, TText } from '@temir/core'
import TLink from '@temir/link'
</script>

<template>
  <TBox
    :margin="5"
    width="20"
    border-style="round"
    justify-content="center"
  >
    <TLink url="https://github.com">
      <TText color="yellow">
        Hi
      </TText>
      <TText color="cyan">
        Github
      </TText>
    </TLink>
  </TBox>
</template>

加载中组件 (Spinner)

<script lang="ts" setup>
import { TBox, TText } from '@temir/core'
import TSpinner from '@temir/spinner'
</script>

<template>
  <TBox
    :margin="5"
    width="20"
    border-style="round"
    justify-content="center"
  >
    <TText>
      <TText color="yellow">
        <TSpinner />
      </TText>
      Loading
    </TText>
  </TBox>
</template>

标签页组件 (Tab)

<script lang="ts" setup>
import { computed, ref } from '@vue/runtime-core'
import { TBox, TText } from '@temir/core'
import { TTab, TTabs } from '@temir/tab'

const tabs = ['Vue', 'React', 'Angular', 'Solid', 'Svelte']
const activeIndex = ref(0)
const selectedText = computed(() => tabs[activeIndex.value])
</script>

<template>
  <TBox>
    <TText>
      Selected Text :
      <TText color="red">
        {{ selectedText }}
      </TText>
    </TText>
  </TBox>

  <TBox>
    <TTabs :on-change="(index) => activeIndex = +index">
      <TTab v-for="item in tabs" :key="item">
        {{ item }}
      </TTab>
    </TTabs>
  </TBox>
</template>

选择组件

<script lang="ts" setup>
import TSelectInput from '@temir/select-input'

const items = [
  {
    label: 'Vue',
    value: 'Vue',
  },
  {
    label: 'Vite',
    value: 'Vite',
  },
  {
    label: 'Temir',
    value: 'Temir',
  },
]
function onSelect(value) {
  console.log('selected', value)
}
</script>

<template>
  <TSelectInput :items="items" :on-select="onSelect" />
</template>

安装

npm install @temir/core

使用

<script lang="ts" setup>
import { ref } from '@vue/runtime-core'
import { TBox, TText } from '@temir/core'
const counter = ref(0)
setInterval(() => {
  counter.value++
}, 100)
</script>

<template>
  <TBox>
    <TText color="green">
      {{ counter }} tests passed
    </TText>
  </TBox>
</template>

HMR支持

前面我们提到了开发者体验(DX),在现在的前端工程中,对开发者很有帮助且提效的就是HMR,这么香的东西Temir没有理由不拥有它,话不多说,直接展示:

开箱即用

使用Temir定制化CLI非常简单,我们提供了@temir/cli帮助你快速构建一个基于Temir的CLI.

mkdir my-temir-cli

cd my-temir-cli

touch main.ts

npm install @temir/cl

# Dev (开发)

temir main.ts

# Build (打包)

temir build main.ts

你可以通过下载这个 例子 来快速开始,你也可以打开 repl.it sandbox来在线体验和尝试它。

演示

Hi Temir

Borders

Table

Vitest

实现

  • createRenderer

Temir的实现主要得益于Vue3出色的跨平台能力,我们可以通过createRenderer API创建一个自定义渲染器,通过创建宿主环境中对应的Node和Element,并对元素进行增删改查操作.

  • Yoga

Vue提供了跑在命令行界面的接口,那我们就还缺少一个布局引擎就能把Vue
跑在命令行工具了.Temir使用了Yoga,一款Flexbox布局引擎.使用你在构建浏览器应用时使用过的类似CSS的属性,为你的CLI构建出色的用户界面。

致谢

  • 这个项目的灵感来源于ink
  • vite-node为实现HMR提供了强力的支持

结语

文章到这里就结束了,如果我的文章和项目对你有所启发和帮助,请给一个star支持作者 ✌

总是有人要赢的,那为什么不能是我呢

4.8k 声望
3.6k 粉丝
0 条评论
推荐阅读
「 2022-年度总结 」我的Vue.js生态开源之旅
大家好,转眼又到一年的尾巴了。好久没写文章了,因为今年工作之余更多的是活跃在开源社区,借着年底思考怀疑人生(偷懒)的空闲时间想跟大家分享今年我在Vue.js生态的做的事情和对开源的看法,也算是「2021」我给V...

null仔3阅读 1k

封面图
从零搭建 Node.js 企业级 Web 服务器(零):静态服务
过去 5 年,我前后在菜鸟网络和蚂蚁金服做开发工作,一方面支撑业务团队开发各类业务系统,另一方面在自己的技术团队做基础技术建设。期间借着 Node.js 的锋芒做了不少 Web 系统,有的至今生气蓬勃、有的早已夭折...

乌柏木140阅读 11.8k评论 10

从零搭建 Node.js 企业级 Web 服务器(十五):总结与展望
总结截止到本章 “从零搭建 Node.js 企业级 Web 服务器” 主题共计 16 章内容就更新完毕了,回顾第零章曾写道:搭建一个 Node.js 企业级 Web 服务器并非难事,只是必须做好几个关键事项这几件必须做好的关键事项就...

乌柏木60阅读 5.9k评论 16

再也不学AJAX了!(二)使用AJAX ① XMLHttpRequest
「再也不学 AJAX 了」是一个以 AJAX 为主题的系列文章,希望读者通过阅读本系列文章,能够对 AJAX 技术有更加深入的认识和理解,从此能够再也不用专门学习 AJAX。本篇文章为该系列的第二篇,最近更新于 2023 年 1...

libinfs39阅读 6.1k评论 12

封面图
从零搭建 Node.js 企业级 Web 服务器(一):接口与分层
分层规范从本章起,正式进入企业级 Web 服务器核心内容。通常,一块完整的业务逻辑是由视图层、控制层、服务层、模型层共同定义与实现的,如下图:从上至下,抽象层次逐渐加深。从下至上,业务细节逐渐清晰。视图...

乌柏木39阅读 7k评论 6

CSS 绘制一只思否猫
欢迎关注我的公众号:前端侦探练习 CSS 有一个比较有趣的方式,就是发挥想象,绘制各式各样的图案,比如来绘制一只思否猫?思否猫,SegmentFault 思否的吉祥物,是一只独一无二、特立独行、热爱自由的(&gt;^ω^&lt...

XboxYan41阅读 2.8k评论 14

封面图
还在用 JS 做节流吗?CSS 也可以防止按钮重复点击
举个例子:一个保存按钮,为了避免重复提交或者服务器考虑,往往需要对点击行为做一定的限制,比如只允许每300ms提交一次,这时候我想大部分同学都会到网上直接拷贝一段throttle函数,或者直接引用lodash工具库

XboxYan34阅读 2.2k评论 2

封面图

总是有人要赢的,那为什么不能是我呢

4.8k 声望
3.6k 粉丝
宣传栏