基于vue-command的web终端

本文记录了使用vue-command开发web终端的过程,包括安装、简单示例和遇到的问题。在缺乏相关资源的情况下,尝试了基本操作并遇到了如提示重复、特定单词限制等问题。建议初级开发者考虑使用更成熟的解决方案如xterm。

使用vue-command开发web终端,不知道能不能完成,在此记录遇到的坑。

基本没有什么资料,找到的都是英文,如果有朋友们遇到好的资料,请留言分享,万分感谢。

1、安装

直接按照官网给出的命令安装vue-command

npm i vue-command --save

2、简单示例

安装完成后在vue新建页面,引入vue-command和对应的css

<template>
  <vue-command :commands="commands" />
</template>

<script>
import VueCommand, { createStdout } from 'vue-command'
import 'vue-command/dist/vue-command.css'

export default {
  components: {
    VueCommand
  },

  data: () =>  ({
    commands: { 
      'hello-world': () => createStdout('Hello world') 
    }
  })
}
</script>

简单的示例,完全是官网的例子,可以运行,得到的基本是这样的。

很简单,然后就没有然后了,对于一个拿来党来说,太难了

自己根据api添加事件,名称,终端标志等。

<template>
  <vue-command :commands="commands" title="收入分摊终端模块" :history=history :not-found="notFound" :pointer="pointer" @input="inputLater" @execute="executing">
    <template slot="prompt" slot-scope="prompt">
      <span class="term-ps" >
      {{ prompter }}
      </span>
    </template>
  </vue-command>

</template>

<script>
  import VueCommand from 'vue-command'
  import 'vue-command/dist/vue-command.css'

  import NanoEditor from './NanoEditor.vue'

  export default {
    data() {
      return {
        pointer: 3,
        prompter: '[RAS~]$',
        notFound: '您输入的指令不存在,请重新输入.',
        history: [],
        commands: {
          nano: () => NanoEditor
        }
      }
    },
    components: {
      VueCommand
    },
    methods:{
      inputLater(a){
        console.log(111)
        console.log(a)
      },
      executing(e,k) {
        console.log('executing')
        console.log(e)
        console.log(k)
      }
    }
  }
</script>

与后台交互的例子

父页面

<template>
  <vue-command
    ref="terminal"
    :commands="commands"
    :history="history"
    :hide-bar="hideBar"
    :is-in-progress="isInProgress"
    :not-found="notFound"
    :pointer="pointer"
    :stdin="stdin"
    :stdout="stdout"
    :intro="intro"
    :show-intro="showIntroFlag"
    :show-help="showHelpFlag"
    title="终端模块"
    @input="inputLater"
    @execute="executing"
    @executed="executed"
  >
    <template slot="prompt" slot-scope="prompt">
      <span class="term-ps" >
        {{ prompter }}
      </span>
    </template>
  </vue-command>

</template>

<script>
import VueCommand, { createStdout, createStderr, createDummyStdout } from 'vue-command'
import 'vue-command/dist/vue-command.css'
import NanoEditor from './NanoEditor.vue'
import ChuckNorris from './ChuckNorris'

const PROMPT = '[RAS~]$'
export default {
  components: {
    VueCommand
  },
  data() {
    return {
      showHelpFlag: true,
      showIntroFlag: true,
      intro: '一些东西需要执行',
      isInProgress: false,
      hideBar: false,
      stdout: '',
      stdin: '',
      pointer: 3,
      prompter: '[RAS~]$',
      notFound: '您输入的指令不存在,请重新输入.',
      history: [],
      commands: {
        cd: undefined,
        norris: () => ChuckNorris,
        nano: () => NanoEditor,
        'hello': () => createStdout('Hello world'),
        'help': () => createStdout(`Available programms:<br><br>
        &nbsp;cd [dir]<br>
        &nbsp;clear<br>
        &nbsp;hello-world<br>
        &nbsp;klieh<br>
        &nbsp;loading [--amount n] [--timeout n]<br>
        &nbsp;nano<br>
        &nbsp;norris<br>
        &nbsp;pokedex pokemon --color<br>
        &nbsp;pwd<br>
        &nbsp;reverse text<br>
      `)
      }
    }
  },
  created() {
    this.commands.cd = ({ _ }) => {
      if ((_[1] === 'home' || _[1] === 'home/') && this.prompt === PROMPT) {
        this.prompt = `${PROMPT}home`

        return createDummyStdout()
      }

      // Navigate from home to root
      if ((_[1] === '../' || _[1] === '..') && this.prompt === `${PROMPT}home`) {
        this.prompt = PROMPT

        return createDummyStdout()
      }

      // Navigate to self
      if (_[1] === '.' || _[1] === './' || typeof _[1] === 'undefined') {
        return createDummyStdout()
      }

      return createStderr(`cd: ${_[1]}: No such file or directory`)
    }
  },
  methods: {
    setHistory(data) {
      this.$refs.terminal.history.push(data)
    },
    inputLater(a) {
      console.log(111)
      console.log(a)
    },
    executing(e, k) {
      this.setIsInProgress = true
      // this.isInProgress = true
      this.stdin = '执行中....'
      this.stdout = '执行了'
      createStdout('执行中....')
      console.log('executing')
      console.log(e)
      console.log(k)
    },
    executed(e, k) {
      // this.isInProgress = false
      this.setIsInProgress = true
      console.log('executed')
      console.log(e)
      console.log(k)
    }
  }
}
</script>

子页面

<template>
  <div>
    <span v-if="!isLoading && !isError">{{ joke }}</span>
    <span v-if="isLoading && !isError">Loading ...</span>
    <span v-if="isError">There was an error getting the joke</span>
  </div>
</template>

<script>
const API = 'https://www.baidu.com'
const API_TIMEOUT = 5000 // 5 seconds

export default {
  inject: ['terminate'],

  data: () => ({
    abortController: new AbortController(),
    isError: false,
    isLoading: true,
    joke: ''
  }),

  async mounted() {
    // Abort getting joke when API request takes longer than defined in "API_TIMEOUT"
    setTimeout(() => {
      if (this.isLoading) {
        this.abortController.abort()
      }
    }, API_TIMEOUT)

    try {
      const response = await fetch(API, { signal: this.abortController.signal })
      if (!response.ok) {
        this.setIsError(true)
        this.terminate()

        return
      }

      const { value } = await response.json()
      this.joke = value
    } catch (error) {
      this.setIsError(true)
    } finally {
      this.isLoading = false
      this.terminate()
    }
  },

  methods: {
    setIsError(isError) {
      this.isError = isError
    }
  }
}
</script>

3、遇到的问题

a.使用prompt,根据官网示例,运行后控制台报错

Duplicate presence of slot "prompt" found in the same render tree - this will likely cause render er

这个遍历使用slot,可以使用作用域插槽,直接代码

<template slot="prompt" slot-scope="prompt">
    <span class="term-ps"  >
      {{ prompter }}
    </span>
</template>

b.prompt使用时候不能重复使用这个单词,比如上个代码段{{prompter}} 这个不能定义为prompt ,不知道什么原因

c.这个真不适合我这种新手

建议还是用xterm吧

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值