首发于taowen

不启动整个应用,单独预览某一个 vue 组件

在阅读了 《写了个 VS Code 中实时预览 Vue/React 组件的插件》 之后,和 jawei 同学聊了一下为啥需要启动整个应用,而不能单独预览某一个组件。发现是因为组件的代码里经常会有一些对上下文的依赖,比如引用 window 上绑定的全局变量,或者发一个 RPC 请求等待服务端返回。于是我们在聊天的过程中想到了一个解决办法。我们知道 vue 组件是长这个样子的

<script lang="ts">
...
</script>
<template>
...
</template>
<style scoped>
...
</style>

那我们只要找到办法只执行 <template> 部分,不执行 <script> 部分不就可以了吗?简单尝试了一下发现是可以的。写法如下

import preview from 'vue-component-preview'
import Todo from './todo.vue';
const TodoPreview = preview(Todo, {
  todos: [{
  }],
  filteredTodos: [{
    id: 1,
    title: 'hello',
    completed: true
  }],
  // when data used but not provided, will callback this
  __get__(p) {
    console.log(p);
  },
  // when child component being rendered, provide its data
  __render__({ componentName, componentType, counter }, props) {
    return {
      todos: [{
            // if child render its own child, it will callback again
            __render__({ componentName, componentType, counter }, props) {
            }
      }],
    }
  }
})

通过 preview 函数的包裹,我们把 Todo 组件变成了 TodoPreview 组件。这个时候去渲染 <TodoPreview> 就只会用 mock 的数据执行 Todo 的 <template> 了。但是 Todo 组件又渲染了子组件,子组件的 <script> 我也不想执行怎么办呢?

这个问题已经被 preview 函数包裹的时候处理了。子组件的渲染会回调 __render__,由你再次提供 mock 的数据。这样就可以拿现有的业务组件出来,直接 preview 它的样式了。以这个为基础,加上 GitHub - divriots/browser-vite: Vite in the browser 甚至可以在浏览器里跑 vite,然后预览 vue 组件。因为文件都是在内存里 vite 编译的,甚至可以实现编辑界面,反向去修改 vue 的源文件。

TodoPreview 注入 data 跑起来的效果

代码没超过 50 行,欢迎 star github.com/taowen/vue-c

编辑于 2022-03-20 08:21