Implementation of Vue single file component

Implementation of Vue single file component

I recently read about vue. I found a single-file component that I had basically overlooked before. Single file components in Vue.js allow all the content of a component to be defined in a single file. That is to say, if we want to bundle a page or a component together, then this single-file component of Vue can do it. As the official website of Vue says, "In many Vue projects, we use app.component to define global components, and then use app.mount('#app') to specify a container element on each page." The components here are relatively simple, but this approach will not work for a more complex project. Here are the reasons:

  • Global definitions enforce that names in each component must not be repeated;
  • String templates lack syntax highlighting, and ugly \ is required when HTML has multiple lines;
  • No CSS support means that when HTML and JavaScript are componentized, CSS is conspicuously left out;
  • No build step Restricts you to HTML and ES5 JavaScript, but not preprocessors such as Pug
  • (formerly Jade) and Babel.

All of this can be solved with single-file components with a .vue extension and using build tools like webpack or Browserify.
So how do you create a single-file component in a Vue project?

Build

npm install -D @vue/compiler-sfc

Enter the above code on the console, and then a folder and another json file will appear. as follows:

insert image description here

If we want to build a single-file component, we have to create the file ourselves. At the same time, you must have a certain understanding of webpack.
For example, we install some required dependencies ourselves. For example, css-loader, css precompilation processor and so on. Because the project needs to parse the vue file, vue-loader is necessary.

These files are actually simple versions of vue. For example, a simple version of the hello.vue file can be as follows

insert image description here

From this we can see: It consists of three parts. The template part is indispensable, and the other two parts, style and script, can be ignored.
Script allows your page js to be perfectly integrated with Vue, and style can use preprocessors to build concise and more functional components. (This single-file component is very similar to the HTML document in the original front-end development. It has its own style tag and script tag, but the presentation layer uses a template tag. Because of the simple method, a powerful layered component (content/template:, presentation:

insert image description here

Some friends may like to split different modules apart, which is what the Vue documentation calls separation of concerns. It doesn’t matter, you can split those documents, separate the css and js into another file, and then import them into the component. as follows:

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

The project directory is as follows:

insert image description here

Among them, index.html

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <title>Vue Simple Todo App with SFC</title>
    <link
      rel="stylesheet"
      href="https://cdnjs.cloudflare.com/ajax/libs/normalize/8.0.1/normalize.min.css" rel="external nofollow" rel="external nofollow" 
    />
    <link rel="stylesheet" href="/dist/main.css" rel="external nofollow" rel="external nofollow" />
  </head>
  <body>
    <div id="app"></div>
    <script src="/dist/main.js"></script>
  </body>
</html>

package.json

{
    "private": true,
    "scripts": {
      "dev": "webpack-dev-server",
      "build": "webpack --env.prod"
    },
    "dependencies": {
      "vue": "^3.1.1"
    },
    "devDependencies": {
      "@vue/compiler-sfc": "^3.1.1",
      "css-loader": "^3.5.2",
      "file-loader": "^6.0.0",
      "mini-css-extract-plugin": "^0.9.0",
      "stylus": "^0.54.7",
      "stylus-loader": "^3.0.2",
      "url-loader": "^4.1.0",
      "vue-loader": "^16.0.0-alpha.3",
      "vue-style-loader": "^4.1.2",
      "webpack": "^4.42.1",
      "webpack-cli": "^3.3.11",
      "webpack-dev-server": "^3.10.3"
    },
    "keywords": ["todo", "vue"],
    "name": "vue-todo-list-app-with-single-file-component",
    "description": "A simple todo list application written in Vue with Single File Component (SFC) support."
  }

webpack.config.js

const path = require("path");
const { VueLoaderPlugin } = require("vue-loader");
const MiniCssExtractPlugin = require("mini-css-extract-plugin");

module.exports = (env = {}) => ({
  mode: env.prod ? "production" : "development",
  devtool: env.prod ? "source-map" : "cheap-module-eval-source-map",
  entry: [
    env.prod ? false : require.resolve(`webpack-dev-server/client`),
    path.resolve(__dirname, "./src/main.js")
  ].filter(Boolean),
  output: {
    path: path.resolve(__dirname, "./dist"),
    publicPath: "/dist/"
  },
  resolve: {
    alias: {
      // this isn't technically needed, since the default `vue` entry for bundlers
      // is a simple `export * from '@vue/runtime-dom`. However having this
      // extra re-export somehow causes webpack to always invalidate the module
      // on the first HMR update and causes the page to reload.
      vue: "@vue/runtime-dom"
    }
  },
  module: {
    rules:
      {
        test: /\.vue$/,
        use: "vue-loader"
      },
      {
        test: /\.png$/,
        use: {
          loader: "url-loader",
          options: { limit: 8192 }
        }
      },
      {
        test: /\.css$/,
        use: [
          {
            loader: MiniCssExtractPlugin.loader,
            options: { hmr: !env.prod }
          },
          "css-loader"
        ]
      },
      {
        test: /\.stylus$/,
        use: ["vue-style-loader", "css-loader", "stylus-loader"]
      },
      {
        test: /\.pug$/,
        loader: "pug-plain-loader"
      }
    ]
  },
  plugins: [
    new VueLoaderPlugin(),
    new MiniCssExtractPlugin({
      filename: "[name].css"
    })
  ],
  devServer: {
    inline: true,
    hot: true,
    stats: "minimal",
    contentBase:__dirname,
    overlay: true,
    injectClient: false,
    disableHostCheck: true
  }
});

test.html

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <title>Vue Simple Todo App with SFC</title>
    <link
      rel="stylesheet"
      href="https://cdnjs.cloudflare.com/ajax/libs/normalize/8.0.1/normalize.min.css" rel="external nofollow" rel="external nofollow" 
    />
    <link rel="stylesheet" href="/dist/main.css" rel="external nofollow" rel="external nofollow" />
  </head>
  <body>
    <div id="app222">test pages</div>
    <script src="/dist/main.js"></script>
  </body>
</html>

There are three files in the src folder, App.vue main.js and TodoItem.vue

Where: App.vue

<template>
  <div class="wrapper">
    <h1>My Todo List</h1>
    <form @submit.prevent="addTodo">
      <input type="text" name="todo-text" v-model="newTodoText" placeholder="New todo">
    </form>
    <ul v-if="todos.length">
      <TodoItem v-for="todo in todos" :key="todo.id" :todo="todo" @remove="removeTodo"/>
    </ul>
    <p class="none" v-else>Nothing left in the list. Add a new todo in the input above.</p>
  </div>
</template>

<script>
import TodoItem from "./TodoItem.vue"

let nextTodoId = 1

const createTodo = text => ({
  text,
  id: nextTodoId++
})

export default {
  components:
    TodoItem
  },

  data() {
    return {
      todos:
        createTodo("Learn Vue"),
        createTodo("Learn about single-file components"),
        createTodo("Fall in love ❤️")
      ],

      newTodoText: ""
    }
  },

  methods: {
    addTodo() {
      const trimmedText = this.newTodoText.trim()

      if (trimmedText) {
        this.todos.push(createTodo(trimmedText))
      }

      this.newTodoText = ""
    },

    removeTodo(item) {
      this.todos = this.todos.filter(todo => todo !== item)
    }
  }
}
</script>

<style lang="stylus">
*, *::before, *::after 
  box-sizing border-box

html, body
  font 16px/1.2 BlinkMacSystemFont, -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif
  padding 10px

.wrapper
  width 75%
  margin 0 auto

form
  margin-bottom 20px

input[type="text"]
  width 100%
  padding 10px
  border 1px solid #777

ul, li
  margin 0
  padding 0

p.none
  color #888
  font-size small
</style>

main.js

import { createApp } from 'vue'
import App from './App.vue'

createApp(App).mount('#app')

TodoItem.vue

<template>
  <li>
    <span>{{ todo.text }}</span>
    <button @click.prevent="$emit('remove', todo)">Remove</button>
  </li>
</template>

<script>
export default {
  props: {
    todo: {
      required: true,
      type: Object
    }
  }
}
</script>


<style lang="stylus" scoped>
li
  display flex
  margin 5px 0

  span
    flex 1
  
  button
    border 1px solid orange
    background orange 
    color white
    font-size 0.8rem
    padding 2px 4px
    cursor pointer

    &:hover
      border-color #ff8100
      background #ff8100
</style>

Note <br /> If you don’t know how to use webpack, it is recommended to follow the instructions on the official website and use the vue scaffolding to install basic tools.
Or you can put the pakage.json I gave you on the project, run npm install to install the most basic environment, and then you can do local development through npm run dev.

In fact, I think this single-file component is already of little use. Unless it is a pure JS project and the libraries and components used are very old, then using this single-file component to develop new functions will have a good effect, provided that you are familiar with Vue. At the same time, I suggest you learn webpack. Don't know nothing about bable and then try to start the project through node.

In fact, using one file to manage html/css/JavaScript in layers and unify them into one file can really make our project look more organized and more standardized. Because in our jq era, CSS is often mixed with HTML, and a simple click event requires them to be separated. This experience is certainly not as clear as "layered management".

References:
1. https://v3.cn.vuejs.org/guide/single-file-component.html#%E5%9C%A8%E7%BA%BF%E6%BC%94%E7%A4%BA
2. https://www.cnblogs.com/houxianzhou/p/14510450.html

This is the end of this article about the implementation of vue single-file components. For more relevant vue single-file component content, please search for previous articles on 123WORDPRESS.COM or continue to browse the following related articles. I hope everyone will support 123WORDPRESS.COM in the future!

You may also be interested in:
  • Vuejs single file component example detailed explanation
  • Use of vuejs single file component.vue file
  • Solve the style loading problem in Vue single file component
  • How to use Vue single file components
  • A new method for implementing single-file components with styles in Vuejs
  • Detailed explanation of three ways to write Vue single file components
  • Vue single file component cannot get $refs problem

<<:  Docker installation tutorial in Linux environment

>>:  MySQL 8.0.15 winx64 installation and configuration method graphic tutorial under windows

Recommend

Summary of several common logs in MySQL

Preface: In the MySQL system, there are many diff...

Solve the installation problem of mysql8.0.19 winx64 version

MySQL is an open source, small relational databas...

How to use jsonp in vue

Table of contents 1. Introduction 2. Installation...

Talk about the understanding of CSS attribute margin

1.What is margin? Margin is used to control the sp...

Vue-Element-Admin integrates its own interface to realize login jump

1. First look at the request configuration file, ...

Detailed explanation of how to install PHP curl extension under Linux

This article describes how to install the PHP cur...

js to realize a simple disc clock

This article shares the specific code of js to im...

Docker connection mongodb implementation process and code examples

After the container is started Log in to admin fi...

Detailed explanation of Vue's simple store

The simplest application of store in Vue is globa...

Alibaba Cloud Server Ubuntu Configuration Tutorial

Since Alibaba Cloud's import of custom Ubuntu...

How to install iso file in Linux system

How to install iso files under Linux system? Inst...

Flex layout realizes the layout mode of upper and lower fixed and middle sliding

This article mainly introduces the layout method ...

Vue Router loads different components according to background data

Table of contents Requirements encountered in act...