Skip to content

Migrate: Single page components #118

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Jun 18, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/.vuepress/components/community/team/vuer-profile.vue
Original file line number Diff line number Diff line change
Expand Up @@ -240,8 +240,8 @@ export default {
color: #4682b4;

&::after {
content: "\f06a";
font-family: FontAwesome;
content: '\f06a';
font-family: 'Font Awesome 5 Free';
font-size: 0.75em;
vertical-align: super;
margin-left: 4px;
Expand Down
10 changes: 8 additions & 2 deletions src/.vuepress/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,13 @@ const sidebar = {
'/guide/composition-api-introduction'
]
},
{
title: 'Tooling',
collapsable: false,
children: [
'/guide/single-file-component'
]
},
{
title: 'Scaling Up',
collapsable: false,
Expand Down Expand Up @@ -131,8 +138,7 @@ module.exports = {
ariaLabel: 'Documentation Menu',
items: [
{ text: 'Guide', link: '/guide/introduction' },
{ text: 'Style Guide', link: '/style-guide/' },
{ text: 'Tooling', link: '/tooling/' }
{ text: 'Style Guide', link: '/style-guide/' }
]
},
{ text: 'API Reference', link: '/api/application-config' },
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/.vuepress/public/images/sfc.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
167 changes: 89 additions & 78 deletions src/.vuepress/styles/index.styl
Original file line number Diff line number Diff line change
@@ -1,88 +1,99 @@
.demo {
font-family: sans-serif;
border: 1px solid #eee;
border-radius: 2px;
padding: 20px 30px;
margin-top: 1em;
margin-bottom: 40px;
user-select: none;
overflow-x: auto;
}
.demo
font-family sans-serif
border 1px solid #eee
border-radius 2px
padding 20px 30px
margin-top 1em
margin-bottom 40px
user-select none
overflow-x auto

.custom-block {
padding: 0.1rem 1.5rem;
margin: 2em 0;
border-left-width: 0.5rem;
border-left-style: solid;
background-color: #f8f8f8;
position: relative;
border-bottom-right-radius: 2px;
border-top-right-radius: 2px;
margin: 1rem 0;
.custom-block
padding 0.1rem 1.5rem
margin 2em 0
border-left-width 0.5rem
border-left-style solid
background-color #f8f8f8
position relative
border-bottom-right-radius 2px
border-top-right-radius 2px
margin 1rem 0

&::before {
position: absolute;
top: 14px;
left: -14px;
color: #fff;
width: 20px;
height: 20px;
border-radius: 100%;
text-align: center;
line-height: 20px;
font-weight: bold;
font-family: 'Dosis', 'Source Sans Pro', 'Helvetica Neue', Arial, sans-serif;
font-size: 14px;
}
&::before
position absolute
top 14px
left -14px
color #fff
width 20px
height 20px
border-radius 100%
text-align center
line-height 20px
font-weight bold
font-family 'Dosis', 'Source Sans Pro', 'Helvetica Neue', Arial, sans-serif
font-size 14px

.custom-block-title {
font-weight: 600;
margin-bottom: -0.4rem;
}
.custom-block-title
font-weight 600
margin-bottom -0.4rem

&.info {
border-color: #007bff;
}
&.info
border-color #007bff

&.tip {
border-color: #42b983;
}
&.tip
border-color #42b983

&.warning {
border-color: #dcbc1e;
background-color: #f8f8f8;
}
&.warning
border-color #dcbc1e
background-color #f8f8f8

&.danger {
border-color: #f66;
background-color: #f8f8f8;
&.danger
border-color #f66
background-color #f8f8f8

&::before {
content: '!';
background-color: #f66;
}
}
&::before
content '!'
background-color #f66

&.details
display block
position relative
border-radius 2px
margin 1.6em 0
padding 1.6em
background-color #eee

h4
margin-top 0

&.details {
display: block;
position: relative;
border-radius: 2px;
margin: 1.6em 0;
padding: 1.6em;
background-color: #eee;
h4 {
margin-top: 0;
}
figure,
p {
&:last-child {
margin-bottom: 0;
padding-bottom: 0;
}
}
summary {
outline: none;
cursor: pointer;
}
}
}
p
&:last-child
margin-bottom 0
padding-bottom 0

summary
outline none
cursor pointer

.scrimba,
.vueschool
background-color #e7ecf3
padding 1em 1.25em
border-radius 2px
color #486491
position relative
margin 24px 0

a
color: #486491
position relative
padding-left 16px

&::before
content "\f144"
font-family 'Font Awesome 5 Free'
font-size 2em
display inline-block
color #73abfe
vertical-align middle
67 changes: 67 additions & 0 deletions src/guide/single-file-component.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
# Single File Components

## Introduction

In many Vue projects, global components will be defined using `app.component()`, followed by `app.mount('#app')` to target a container element in the body of every page.

This can work very well for small to medium-sized projects, where JavaScript is only used to enhance certain views. In more complex projects however, or when your frontend is entirely driven by JavaScript, these disadvantages become apparent:

- **Global definitions** force unique names for every component
- **String templates** lack syntax highlighting and require ugly slashes for multiline HTML
- **No CSS support** means that while HTML and JavaScript are modularized into components, CSS is conspicuously left out
- **No build step** restricts us to HTML and ES5 JavaScript, rather than preprocessors like Pug (formerly Jade) and Babel

All of these are solved by **single-file components** with a `.vue` extension, made possible with build tools such as Webpack or Browserify.

Here's an example of a file we'll call `Hello.vue`:

<a href="https://codepen.io/team/Vue/pen/3de13b5cd0133df4ecf307b6cf2c5f94" target="_blank" rel="noopener noreferrer"><img src="/images/sfc.png" width="403" alt="Single-file component example (click for code as text)" style="display: block; margin: 15px auto; max-width: 100%"></a>

Now we get:

- [Complete syntax highlighting](https://github.com/vuejs/awesome-vue#source-code-editing)
- [CommonJS modules](https://webpack.js.org/concepts/modules/#what-is-a-webpack-module)
- [Component-scoped CSS](https://vue-loader.vuejs.org/en/features/scoped-css.html)

As promised, we can also use preprocessors such as Pug, Babel (with ES2015 modules), and Stylus for cleaner and more feature-rich components.

<a href="https://codesandbox.io/s/vue-single-file-component-with-pre-processors-mr3ik?file=/src/App.vue" target="_blank" rel="noopener noreferrer"><img src="/images/sfc-with-preprocessors.png" width="563" alt="Single-file component with pre-processors example (click for code as text)" style="display: block; margin: 15px auto; max-width: 100%"></a>

These specific languages are only examples. You could as easily use TypeScript, SCSS, PostCSS, or whatever other preprocessors that help you be productive. If using Webpack with `vue-loader`, it also has first-class support for CSS Modules.

### What About Separation of Concerns?

One important thing to note is that **separation of concerns is not equal to separation of file types.** In modern UI development, we have found that instead of dividing the codebase into three huge layers that interweave with one another, it makes much more sense to divide them into loosely-coupled components and compose them. Inside a component, its template, logic and styles are inherently coupled, and collocating them actually makes the component more cohesive and maintainable.

Even if you don't like the idea of Single-File Components, you can still leverage its hot-reloading and pre-compilation features by separating your JavaScript and CSS into separate files:

``` html
<!-- my-component.vue -->
<template>
<div>This will be pre-compiled</div>
</template>
<script src="./my-component.js"></script>
<style src="./my-component.css"></style>
```

## Getting Started

### Example Sandbox

If you want to dive right in and start playing with single-file components, check out [this simple todo app](https://codesandbox.io/s/vue-todo-list-app-with-single-file-component-vzkl3?file=/src/App.vue) on CodeSandbox.

### For Users New to Module Build Systems in JavaScript

With `.vue` components, we're entering the realm of advanced JavaScript applications. That means learning to use a few additional tools if you haven't already:

- **Node Package Manager (NPM)**: Read the [Getting Started guide](https://docs.npmjs.com/packages-and-modules/getting-packages-from-the-registry) section about how to get packages from the registry.

- **Modern JavaScript with ES2015/16**: Read through Babel's [Learn ES2015 guide](https://babeljs.io/docs/en/learn). You don't have to memorize every feature right now, but keep this page as a reference you can come back to.

After you've taken a day to dive into these resources, we recommend checking out [Vue CLI](https://cli.vuejs.org/). Follow the instructions and you should have a Vue project with `.vue` components, ES2015, webpack and hot-reloading in no time!

### For Advanced Users

The CLI takes care of most of the tooling configurations for you, but also allows fine-grained customization through its own [config options](https://cli.vuejs.org/config/).

In case you prefer setting up your own build setup from scratch, you will need to manually configure webpack with [vue-loader](https://vue-loader.vuejs.org). To learn more about webpack itself, check out [their official docs](https://webpack.js.org/configuration/) and [webpack learning academy](https://webpack.academy/p/the-core-concepts).
2 changes: 1 addition & 1 deletion src/style-guide/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -1810,7 +1810,7 @@ $color-priority-d: #3f536d;
margin-top: 0;

&::before {
font-family: FontAwesome;
font-family: 'Font Awesome 5 Free';
margin-right: .4em;
}
}
Expand Down