2025-06-11 22:23:49 +08:00

19 KiB

Vue SFC

Vue.js, The Progressive JavaScript Framework, is an approachable, performant and versatile framework for building web user interfaces.

This is the documentation for LiveCodes language support for Vue Single-File Component (SFC).

The support for Vue 2 SFC (the older, EOL version) is documented separately.

Usage

Vue SFC can be used as documented in the specs, including support for Scoped CSS, CSS Modules, pre-processors, JSX and src imports. See below for usage.

Demo

import LiveCodes from '../../src/components/LiveCodes.tsx'; import RunInLiveCodes from '../../src/components/RunInLiveCodes.tsx';

Scoped CSS

When a <style> tag has the scoped attribute, its CSS will apply to elements of the current component only.

docs

export const scopedCssDemo = { vue: <style scoped>\n.example {\n color: red;\n}\n</style>\n\n<template>\n <div class="example">hi</div>\n</template>, };

<RunInLiveCodes params={scopedCssDemo} code={scopedCssDemo.vue} language="html" formatCode={false}

CSS Modules

A <style module> tag is compiled as CSS Modules and exposes the resulting CSS classes to the component as an object under the key of $style.

docs

export const cssModulesDemo = { vue: <template>\n <p :class="$style.red">This should be red</p>\n</template>\n\n<style module>\n.red {\n color: red;\n}\n</style>, };

<RunInLiveCodes params={cssModulesDemo} code={cssModulesDemo.vue} language="html" formatCode={false}

CSS Frameworks

CSS Frameworks#css-processors) supported in LiveCodes (e.g. Tailwind CSS, UnoCSS, WindiCSS) can detect class names added in Vue SFCs. Make sure that the required utility is enabled (from style editor menu or in processors property of configuration object#processors)).

See example below.

Languages and Pre-Processors

Blocks can declare pre-processor languages using the lang attribute.

docs

Many of the languages supported in LiveCodes can be used. The value of lang attribute can be the language name (specified in its documentation page) or any of its aliases (extensions).

export const processorsDemo = { vue: <template lang="pug">\nh1 {{ msg }}\n</template>\n\n<script lang="ts" setup>\n const msg: string = 'Hello!'\n</script>\n\n<style lang="scss">\n $primary-color: #666;\n body {\n color: $primary-color;\n }\n</style>\n, };

<RunInLiveCodes params={processorsDemo} code={processorsDemo.vue} language="html" formatCode={false}

JSX

JSX can be used in render functions without needing any configuration.

export const jsxDemo = { vue: <script>\n export default {\n data() {\n return {\n counter: 0,\n align: "center",\n };\n },\n methods: {\n increment() {\n this.counter += 1;\n },\n },\n render() {\n return (\n <div class="container">\n <h1>Hello, Vue!</h1>\n <p>You clicked {this.counter} times.</p>\n <button onClick={this.increment}>Click me</button>\n </div>\n );\n },\n };\n</script>\n\n<style scoped>\n .container,\n .container button {\n text-align: v-bind("align");\n font: 1em sans-serif;\n }\n .logo {\n width: 150px;\n }\n</style>, };

<RunInLiveCodes params={jsxDemo} code={jsxDemo.vue} language="html" formatCode={false}

src Imports

The src attribute can be used to import an external file for a language block:

<template src="https://my-website.com/template.html"></template>
<style src="https://my-website.com/style.css"></style>
<script src="https://my-website.com/script.js"></script>

The value of src attribute can be either:

  • Absolute URL (e.g. https://unpkg.com/todomvc-app-css/index.css)
  • Path in npm package (e.g. todomvc-app-css/index.css)

Relative paths (e.g. ./my-styles.css) cannot be used (because there is no file system in LiveCodes).

The imported sources can use any of the supported languages/pre-processors (identified by the file extension or can be specified by lang attribute).

Module Imports

npm modules can be imported as described in the section about module resolution, including bare module imports and importing from different CDNs. Stylesheets imported in the script block are added as <link rel="stylesheet"> tags in the page head.

Example:

export const importsDemo = { vue: <script setup>\n import { ref } from 'vue';\n import confetti from 'canvas-confetti';\n import "bootstrap/dist/css/bootstrap.css"\n\n const count = ref(0);\n function increment() {\n count.value++;\n confetti();\n }\n</script>\n\n<template>\n <div class="m-5 text-center">\n <p>You clicked {{ count }} times.</p>\n <button @click="increment()">Click me</button>\n </div>\n</template>\n, };

<RunInLiveCodes params={importsDemo} code={importsDemo.vue} language="html" formatCode={false}

Module imports can be customized using import maps as described in module resolution#custom-module-resolution) documentations.

Multiple Components

Vue is supported in both markup#markup-editor) and script#script-editor) editors.

This allows having a component in the markup editor that imports (and passes props to) a component in the script editor. The opposite is not supported.

This can be done using relative import of a file name in the same directory. Any file name will resolve to the component in the script editor, e.g. ./script.vue, ./Component.vue, ./Counter.vue, etc.

export const multi = { markup: { language: 'vue', content: `

`, }, script: { language: 'vue', content: `
{{ count }}
- +
Reset
`, }, style: { language: 'css', content: '@import "tailwindcss";\n', }, processors: ['tailwindcss'], }

Please note that LiveCodes does not have the concept of a file system. However, you can configure editor options#markup) like title, order and hideTitle to simulate multiple files, change editor order or even hide editors.

Example:

export const multiFiles = { ...multi, markup: { ...multi.markup, title: 'App.vue', }, script: { ...multi.script, title: 'Counter.vue', }, style: { ...multi.style, title: 'styles.css', order: 3, }, };

When both markup and script editors use Vue, the component in the markup editor is used as the main component rendered in the root element. To render the component in the script editor, it has to be imported and used by the main component.

Importing External SFCs

External Vue SFCs can be imported. The import URL has to be an absolute URL ending with .vue extension. Any bare or relative imports in the imported files are resolved and compiled recursively.

This is an example of importing a Vue SFC, which in turn imports other Vue SFCs (the imported components use Tailwind CSS, which is enabled in this project as a CSS preprocessor):

export const importExternal = { activeEditor: 'script', script: { language: 'vue', content: `

` }, style: { language: 'css', content: '@import "tailwindcss";\n', }, processors: ['tailwindcss'], }

Please note that extensionless imports are not supported. However, you may customize the import URL using import maps as described in module resolution#custom-module-resolution) section.

Example:

{
  "imports": {
    "https://raw.githubusercontent.com/hatemhosny/vue3-samples/master/src/composable/useTodoList": "https://raw.githubusercontent.com/hatemhosny/vue3-samples/master/src/composable/useTodoList.js",
    "https://raw.githubusercontent.com/hatemhosny/vue3-samples/master/src/composable/useMousePosition": "https://raw.githubusercontent.com/hatemhosny/vue3-samples/master/src/composable/useMousePosition.js"
  }
}

export const importExternalWithImportMap = { activeEditor: 'script', script: { language: 'vue', content: `

`, }, imports: { "https://raw.githubusercontent.com/hatemhosny/vue3-samples/master/src/composable/useTodoList": "https://raw.githubusercontent.com/hatemhosny/vue3-samples/master/src/composable/useTodoList.js", "https://raw.githubusercontent.com/hatemhosny/vue3-samples/master/src/composable/useMousePosition": "https://raw.githubusercontent.com/hatemhosny/vue3-samples/master/src/composable/useMousePosition.js" } };

Importing Data URLs

You may want to import other SFCs without having to host them on a server. These components can be encoded as data URLs and imported as usual.

The data URL has to start with data:text/vue to be recognized as a Vue SFC. Any imports in the imported URLs (even if they are also data URLs) are resolved and compiled recursively.

:::info

The code in any code editor can be encoded as data URL from the LiveCodes UI using the "Copy code as data URL" button below the code editor.

:::

This is the previous demo that uses data URLs (with nested imports) instead of external URLs:

export const importDataUrls = { activeEditor: 'script', script: { language: 'vue', content: `

` }, style: { language: 'css', content: '@import "tailwindcss";\n', }, processors: ['tailwindcss'], }

In the above demo, this component is imported:

data:text/vue;charset=UTF-8;base64,PHNjcmlwdCBzZXR1cCBsYW5nPSJ0cyI+DQppbXBvcnQgeyByZWYgfSBmcm9tICJ2dWUiOw0KaW1wb3J0IFByaW1hcnlCdXR0b24gZnJvbSAiZGF0YTp0ZXh0L3Z1ZTtjaGFyc2V0PVVURi04O2Jhc2U2NCxQSE5qY21sd2RDQnpaWFIxY0NCc1lXNW5QU0owY3lJK0RRcGtaV1pwYm1WUWNtOXdjeWg3RFFvZ0lIUnBkR3hsT2lCN0RRb2dJQ0FnZEhsd1pUb2dVM1J5YVc1bkxBMEtJQ0FnSUdSbFptRjFiSFE2SUNKQ2RYUjBiMjRpTEEwS0lDQjlMQTBLZlNrN0RRbzhMM05qY21sd2RENE5DZzBLUEhSbGJYQnNZWFJsUGcwS0lDQThZblYwZEc5dURRb2dJQ0FnWTJ4aGMzTTlJblJsZUhRdGJXUWdabTl1ZEMxdFpXUnBkVzBnWW1jdFozSmhlUzAxTURBZ2FHOTJaWEk2WW1jdFozSmhlUzAyTURBZ2RISmhibk5wZEdsdmJpQndlUzB4SUhCNExUUWdkR1Y0ZEMxM2FHbDBaU0J5YjNWdVpHVmtJR1J5YjNBdGMyaGhaRzkzTFhoc0lnMEtJQ0ErRFFvZ0lDQWdlM3NnZEdsMGJHVWdmWDBOQ2lBZ1BDOWlkWFIwYjI0K0RRbzhMM1JsYlhCc1lYUmxQZz09IjsNCmltcG9ydCBEYW5nZXJCdXR0b24gZnJvbSAiZGF0YTp0ZXh0L3Z1ZTtjaGFyc2V0PVVURi04O2Jhc2U2NCxQSE5qY21sd2RDQnpaWFIxY0NCc1lXNW5QU0owY3lJK0RRcGtaV1pwYm1WUWNtOXdjeWg3RFFvZ0lIUnBkR3hsT2lCN0RRb2dJQ0FnZEhsd1pUb2dVM1J5YVc1bkxBMEtJQ0FnSUdSbFptRjFiSFE2SUNKQ2RYUjBiMjRpTEEwS0lDQjlMQTBLZlNrN0RRbzhMM05qY21sd2RENE5DZzBLUEhSbGJYQnNZWFJsUGcwS0lDQThZblYwZEc5dURRb2dJQ0FnWTJ4aGMzTTlJblJsZUhRdGJXUWdabTl1ZEMxdFpXUnBkVzBnWW1jdGNtVmtMVFV3TUNCb2IzWmxjanBpWnkxeVpXUXROakF3SUhSeVlXNXphWFJwYjI0Z2NIa3RNU0J3ZUMwMElIUmxlSFF0ZDJocGRHVWdjbTkxYm1SbFpDQmtjbTl3TFhOb1lXUnZkeTE0YkNJTkNpQWdQZzBLSUNBZ0lIdDdJSFJwZEd4bElIMTlEUW9nSUR3dlluVjBkRzl1UGcwS1BDOTBaVzF3YkdGMFpUND0iOw0KDQpjb25zdCBjb3VudCA9IHJlZigwKTsNCjwvc2NyaXB0Pg0KDQo8dGVtcGxhdGU+DQogIDxkaXYgY2xhc3M9InctZnVsbCBtdC04IGZsZXgganVzdGlmeS1jZW50ZXIiPg0KICAgIDxzcGFuIHJlZj0iY291bnRlciIgY2xhc3M9InRleHQtM3hsIGZvbnQtYm9sZCI+e3sgY291bnQgfX08L3NwYW4+DQogIDwvZGl2Pg0KICA8ZGl2IGNsYXNzPSJ3LWZ1bGwgbXQtNCBmbGV4IGZsZXgtcm93IHNwYWNlLXgtNCBqdXN0aWZ5LWNlbnRlciI+DQogICAgPHByaW1hcnktYnV0dG9uIHJlZj0iZGVjcmVtZW50QnV0dG9uIiB0aXRsZT0iLSIgQGNsaWNrPSJjb3VudC0tIiAvPg0KICAgIDxwcmltYXJ5LWJ1dHRvbiByZWY9ImluY3JlbWVudEJ1dHRvbiIgdGl0bGU9IisiIEBjbGljaz0iY291bnQrKyIgLz4NCiAgPC9kaXY+DQogIDxkaXYgY2xhc3M9InctZnVsbCBtdC00IGZsZXggZmxleC1yb3cgc3BhY2UteC00IGp1c3RpZnktY2VudGVyIj4NCiAgICA8ZGFuZ2VyLWJ1dHRvbiByZWY9InJlc2V0QnV0dG9uIiB0aXRsZT0iUmVzZXQiIEBjbGljaz0iY291bnQgPSAwIiAvPg0KICA8L2Rpdj4NCjwvdGVtcGxhdGU+

which imports these:

data:text/vue;charset=UTF-8;base64,PHNjcmlwdCBzZXR1cCBsYW5nPSJ0cyI+DQpkZWZpbmVQcm9wcyh7DQogIHRpdGxlOiB7DQogICAgdHlwZTogU3RyaW5nLA0KICAgIGRlZmF1bHQ6ICJCdXR0b24iLA0KICB9LA0KfSk7DQo8L3NjcmlwdD4NCg0KPHRlbXBsYXRlPg0KICA8YnV0dG9uDQogICAgY2xhc3M9InRleHQtbWQgZm9udC1tZWRpdW0gYmctZ3JheS01MDAgaG92ZXI6YmctZ3JheS02MDAgdHJhbnNpdGlvbiBweS0xIHB4LTQgdGV4dC13aGl0ZSByb3VuZGVkIGRyb3Atc2hhZG93LXhsIg0KICA+DQogICAge3sgdGl0bGUgfX0NCiAgPC9idXR0b24+DQo8L3RlbXBsYXRlPg==
data:text/vue;charset=UTF-8;base64,PHNjcmlwdCBzZXR1cCBsYW5nPSJ0cyI+DQpkZWZpbmVQcm9wcyh7DQogIHRpdGxlOiB7DQogICAgdHlwZTogU3RyaW5nLA0KICAgIGRlZmF1bHQ6ICJCdXR0b24iLA0KICB9LA0KfSk7DQo8L3NjcmlwdD4NCg0KPHRlbXBsYXRlPg0KICA8YnV0dG9uDQogICAgY2xhc3M9InRleHQtbWQgZm9udC1tZWRpdW0gYmctcmVkLTUwMCBob3ZlcjpiZy1yZWQtNjAwIHRyYW5zaXRpb24gcHktMSBweC00IHRleHQtd2hpdGUgcm91bmRlZCBkcm9wLXNoYWRvdy14bCINCiAgPg0KICAgIHt7IHRpdGxlIH19DQogIDwvYnV0dG9uPg0KPC90ZW1wbGF0ZT4=

Root Element

To mount the application instance to a specific DOM element use "livecodes-app" as the element id in the HTML. Otherwise, if that element is not found, a new div element is added to document.body and is used to mount the instance.

Example:

export const customRoot = { markup: { language: 'html', content: `

Custom Root Element

...other page content

`, }, script: { language: 'vue', content: `I'm a Vue SFC`, }, };

Language Info

Name

vue

Extensions

.vue, .vue3

Editor

script, markup

Compiler

The official @vue/compiler-sfc.

Version

@vue/compiler-sfc: v3.5.13

Code Formatting

Using Prettier.

Limitations

Currently, Vue support has the following limitations:

  • SSR is not supported.
  • The defineProps() macro cannot infer props from TypeScript types not defined in the same file.

PRs are welcome.

Starter Template

https://livecodes.io/?template=vue