Vue在线编译器

戳蓝字"

前端优选

"

关注我们哦

来源:优快云 本文链接:https://blog.youkuaiyun.com/WangYangsea/article/details/95237722

现在网络上,有非常多的JS在线编译器,非常好用,特备是在调试某些片段代码的时候,比在本地重新新建文件来的方便快捷~ 非常流行的比如  JS.do、  jsfiddle、JSRUN 等等。

而对于Vue来说,在线编译器有时候会显得更加必要,因为初始化一个Vue项目还是需要花一点时间的~并且需要安卓很多的依赖,费时费力。现在也有很多JS在线编译器已经支持Vue代码了,另外流行的Vue框架)IView也有一个专门的在线编译器 IView Run,不止支持Vue,还支持IView 相关组件~。

接下来,我们两写一个功能相似的乞丐版Vue在线编译器 vue-running。

首先我们来看一下demo效果:

 vue在线编译效果

extend 和 $mount

在开始之前,我们先来了解一下Vue的两个不是很常用的API extend 和 $mount。

我们在使用 vue-cli + webpack构建一个新的工程的时候, 入口JS文件main.js中最后 总会看到这么一段:

new Vue({
  el: '#app',
  router,
  components: { App },
  template: '<App/>'
})

在创建一个Vue实例的时候,我们都有一个el属性,决定这个实例需要挂载在那个节点上(根节点),如果没有el属性,那么该实例处于未挂载状态。

  • Vue.extend()就是利用Vue的构造器功能,创建一个子类,但是属于未挂载状态;

  • $mount 就是一个手动去挂载Vue实例的方法。

我们可以看官方文档给的实例:

<div id="mount-point"></div>
// 创建构造器
var Profile = Vue.extend({
  template: '<p>{{firstName}} {{lastName}} aka {{alias}}</p>',
  data: function () {
    return {
      firstName: 'Walter',
      lastName: 'White',
      alias: 'Heisenberg'
    }
  }
})
// 创建 Profile 实例,并挂载到一个元素上。
new Profile().$mount('#mount-point')

结果如下:

<div id="mount-point">
 <p>Walter White aka Heisenberg</p>
</div>

vm.$mount()相关说明

「今天所说的 vue-running小demo,就是基于这两个属性做的」

分析

通常,我们Vue项目中的.vue文件构成如下:

<template>
  ......
</template>
<script>
export default {
  ......
</script>
<style scoped>
......
</style>
  • template 为HTML模板

  • script 为组件的数据、方法等

  • style css样式相关

我们回看上面extend方法,其实.vue文件中的 就代表 extend中 template,script中代表extend中的其他选项。style我们稍后再处理。

通过上面分析,首先我们得将.vue文件中的内容进行匹配分割,然后用Vue.extend()创建子类,最后挂载~。

首先我们在components文件夹下面新建:

  1. index.vue vue-running的显示页面

  2. edit.vue 编辑Vue代码的组件

  3. running.vue 最终编辑完的实例挂载之后显示的内容

首先我们看edit.vue:

<template>
  <div class="edit-box">
    <div class="btn-box">
      <button @click="handleClick">运行代码</button>
      <button class="edit" @click="edit">重新编辑</button>
    </div>
    <div class="style-box">
      <textarea :disabled="disabled" name="code" placeholder="请在此编写.vue文件" @input="handleChange"></textarea>
    </div>
  </div>
</template>
<script>
export default {
  name: 'edit',
  props: {
    value: {
      type: String,
      default: ''
    }
  },
  data () {
    return {
      currentValue: this.value,
      disabled: false
    }
  },
  methods: {
    handleChange (e) {
      const val = e.target.value
      this.$emit('input', val)
    },
    handleClick () {
      this.$emit('running')
      if (this.currentValue) {
        this.disabled = true
      }
    },
    edit () {
      this.disabled = false
    }
  }
}
</script>

其实功能比较简单,就是一个双向数据绑定的textarea输入框。外加 运行 和重新编辑 两个按钮,并将事件向外”广播“。

接下来我们看running.vue:

<template>
  <div class="hello">
    <h3 class="title">运行结果</h3>
    <div class="code-box" id="display"></div>
  </div>
</template>

<script>
import Vue from 'vue'
export default {
  name: 'running',
  props: {
    value: {
      type: String,
      default: ''
    }
  },
  data () {
    return {
      code: this.value,
      html: '',
      js: '',
      css: '',
      program: null
    }
  },
  watch: {
    value (val) {
      this.code = val
    }
  },
  methods: {
    getSource (source, type) {
      const regex = new RegExp(`<${type}[^>]*>`)
      let openingTag = source.match(regex)
      if (!openingTag) return ''
      else openingTag = openingTag[0]

      return source.slice(
        source.indexOf(openingTag) + openingTag.length,
        source.lastIndexOf(`</${type}>`)
      )
    },
    splitCode () {
      const script = this.getSource(this.code, 'script').replace(
        /export default/,
        'return '
      )
      const style = this.getSource(this.code, 'style')
      const template =
        '<div id="code-running">' +
        this.getSource(this.code, 'template') +
        '</div>'
      this.js = script
      this.css = style
      this.html = template
    },
    buildDom () {
      this.splitCode()
      if (this.html === '' || this.js === '') {
        this.$toast({
          msg: `请输入有效的Vue代码${Math.floor(Math.random() * 1000)}`
        })
        // eslint-disable-next-line semi
        return;
      }
      // eslint-disable-next-line no-new-func
      const common = new Function(this.js)()
      common.template = this.html
      const Template = Vue.extend(common)
      this.program = new Template()
      document.querySelector('#display').appendChild(this.program.$mount().$el)
      if (this.css !== '') {
        const styles = document.createElement('style')
        styles.type = 'text/css'
        styles.innerHTML = this.css
        document.getElementsByTagName('head')[0].appendChild(styles)
      }
    },
    reset () {
      document.getElementById('display').innerHTML = ''
      if (this.program) {
        this.program.$destroy()
      }
      this.program = null
    }
  }
}
</script>

稍作分析:

  • 该组件props接受一个value,string类型的,就是我们在线编辑的.vue文件代码;

  • data里面定义了 code: this.value ,另外定义了被分割好之后的代码片段js html css;

  • methods里面定义的方法 getSource() 通过正则匹配分割代码并去除最外层的

点个在看,大家都看 

### 使用 Vue 编译器的方法 #### 安装环境 为了使用 Vue 编译器,推荐采用官方首推且完全免费的编辑器——Visual Studio Code (VsCode)[^1]。确保已经下载并安装好 VsCode。 #### 创建项目结构 当通过 `vue-cli` 和 Webpack 构建新工程项目时,在入口 JavaScript 文件 `main.js` 中通常会有如下配置: ```javascript new Vue({ el: '#app', router, components: { App }, template: '<App/>' }); ``` 这段代码初始化了一个新的 Vue 实例,并指定了挂载点以及根组件[^3]。 #### 配置编译选项 对于模板内的编写方式有两种主要形式:一种是在单文件组件 `.vue` 文件内部定义;另一种则是利用内联模板属性直接在 HTML 标签上指定。例如下面展示了如何以内联的方式创建一个简单的自定义组件: ```html <!-- 内联模板 --> Vue.component('my-component', { template: `<div>{{ message }}</div>`, data() { return { message: 'Hello Vue!' }; } }) ``` 这种方式能够减少一次单独解析 SFC 的过程,简化开发流程[^2]。 #### 虚拟 DOM 差异化算法优化 值得注意的是,编译阶段的一个重要功能是对虚拟 DOM 进行处理。具体来说,编译器可以根据静态分析的结果来告知渲染引擎哪些部分可能发生变动,从而使得更新操作更加高效。比如在一个复杂的页面布局里如果仅有某个特定区域的数据发生了更改,则可以通过编译后的提示仅对该范围执行重绘逻辑而不是整个视图树[^4]。 #### 启动本地服务器与调试工具 完成上述设置之后就可以启动本地服务来进行实时预览和调试了。一般情况下,这一步骤也是由脚手架工具自动完成的,只需按照命令行指示输入相应指令即可开启监听模式。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值