之前都是在html文件中写组件的css,组件的js,组件的模板来演示vue组件的语法,下面介绍以.vue结尾的单文件组件。vue-loader是一个Webpack的loader,可以将单文件组件转换为JavaScript模块。
一、基本组成
单文件组件中包含<template>、<script>、<style>三种代码块。
<template>默认语言是html,内容将被提取为字符串,编译结果作为Vue组件的template选项,一个.vue文件最多包含一个<template>代码块。
<script>默认语言是js,如果检测到babel-loader的配置,将自动支持es6语法,一个.vue文件最多包含一个<script>代码块。
<style>默认语言是css,默认使用style-loader提取内容,并通过<style>标签动态加入文档的<head> 中,一个.vue文件可以包含多个<style>代码块。<style>标签有scoped属性时,它的css只作用于当前组件中的元素。

二、运行时构建的demo
1、新建package.json文件

  1. {
  2. "name": "vuetest",
  3. "version": "1.0.0",
  4. "description": "",
  5. "scripts": {
  6. "test": "echo \"Error: no test specified\" && exit 1",
  7. "server": "webpack-dev-server --open",
  8. "build": "webpack-dev-server"
  9. },
  10. "author": "camille",
  11. "license": "ISC",
  12. "devDependencies": {
  13. "css-loader": "^0.28.7",
  14. "style-loader": "^0.19.0",
  15. "vue": "^2.5.2",
  16. "vue-loader": "^13.3.0",
  17. "vue-template-compiler": "^2.5.1"
  18. }
  19. }

2、新建webpack.config.js文件

  1. module.exports = {
  2. entry: './main.js',
  3. output: {
  4. path: __dirname,
  5. filename: 'bundle.js'
  6. },
  7. devtool: "inline-source-map",
  8. module: {
  9. rules: [
  10. {
  11. test: /\.vue$/,
  12. loader: 'vue-loader'
  13. },
  14. {
  15. test: /\.css$/,
  16. use: ['style-loader','css-loader']
  17. }
  18. ]
  19. }
  20. }

3、新建index.html文件

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>单文件组件运行时构建</title>
  6. </head>
  7. <body>
  8. <div id="J_vapp"></div>
  9. <script type="text/javascript" src="bundle.js"></script>
  10. </body>
  11. </html>

4、新建hello.vue单文件组件

  1. <template>
  2. <p>{{ greeting }},vue</p>
  3. </template>
  4. <script>
  5. module.exports={
  6. data:function(){
  7. return {
  8. greeting:"hello"
  9. }
  10. }
  11. }
  12. </script>
  13.  
  14. <style scoped>
  15. p{
  16. font-size:15px;
  17. color:red;
  18. }
  19. </style>

5、新建main.js文件

  1. import Vue from 'vue'
  2. import sfile from './hello.vue'
  3. var vm = new Vue({
  4. el: '#J_vapp',
  5. render: function(h){
  6. return h(sfile)
  7. }
  8. })

6、渲染结果

  1. <p data-v-d0145a06="">hello,vue</p>

可以看出html中的J_vapp相当于桥梁,最后不会出现在dom中。
7、疑惑
我明明没有安装babel-loader,为什么上面可以用import from方式引入模块,而且没报错?vue-loader的v13.0.0版本告诉我,.vue文件将被默认为一个es模块。

四、运行时构建demo的另一种表达
众所周知,在main.js中既可以用import引入文件,也可以用require,下面就用require引入。

1、修改main.js文件

  1. var Vue = require('vue')
  2. var sfile = require('./hello.vue')
  3.  
  4. var vm = new Vue({
  5. el: '#J_vapp',
  6. render: function(h){
  7. return h(sfile)
  8. }
  9. })

紧接着出现“Vue is not a constructor”问题。

2、修改webpack.config.js文件

  1. module.exports = {
  2. entry: './main.js',
  3. output: {
  4. path: __dirname,
  5. filename: 'bundle.js'
  6. },
  7. devtool: "inline-source-map",
  8. module: {
  9. rules: [
  10. {
  11. test: /\.vue$/,
  12. loader: 'vue-loader'
  13. },
  14. {
  15. test: /\.css$/,
  16. use: ['style-loader','css-loader']
  17. }
  18. ]
  19. },
  20. resolve: {
  21. alias: {
  22. vue$: 'vue/dist/vue.js', //vue$表示精确匹配
  23. }
  24. }
  25. }

前面那个问题解决了,接着又有“Failed to mount component: template or render function not defined.”问题。

3、修改main.js文件

各种探索,终于在vue-loader变更这里找到问题根源,如果依赖了v13+的vue-loader,用require引入.vue文件时,后面加上default。

  1. var Vue = require('vue')
  2. var sfile = require('./hello.vue').default
  3.  
  4. var vm = new Vue({
  5. el: '#J_vapp',
  6. render: function(h){
  7. return h(sfile)
  8. }
  9. })

五、独立构建的demo
1、新建package.json文件
同运行时构建。
2、新建webpack.config.js文件

  1. module.exports = {
  2. entry: './main.js',
  3. output: {
  4. path: __dirname,
  5. filename: 'bundle.js'
  6. },
  7. devtool: "inline-source-map",
  8. module: {
  9. rules: [
  10. {
  11. test: /\.vue$/,
  12. loader: 'vue-loader'
  13. },
  14. {
  15. test: /\.css$/,
  16. use: ['style-loader','css-loader']
  17. }
  18. ]
  19. },
  20. resolve: {
  21. alias: {
  22. vue$: 'vue/dist/vue.js' //vue$表示精确匹配
  23. }
  24. }
  25. }

注意:如果没有resolve的配置,这里会报错。You are using the runtime-only build of Vue where the template compiler is not available. Either pre-compile the templates into render functions, or use the compiler-included build.

3、新建index.html文件

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>单文件组件,独立构建,模板命名很重要</title>
  6. </head>
  7. <body>
  8. <div id="J_vapp">
  9. <temptpl></temptpl>
  10. </div>
  11. <script type="text/javascript" src="bundle.js"></script>
  12. </body>
  13. </html>

4、新建hello.vue单文件组件

  1. <template>
  2. <p>{{greeting}},vue</p>
  3. </template>
  4. <script type="text/javascript">
  5. export default {
  6. data:function(){
  7. return {
  8. greeting:"hello"
  9. }
  10. }
  11. }
  12. </script>
  13.  
  14. <style scoped>
  15. p{
  16. font-size:15px;
  17. color:red;
  18. }
  19. </style>

5、新建main.js文件

  1. import Vue from 'vue'
  2. import temptpl from './hello.vue'
  3. var vm = new Vue({
  4. el: '#J_vapp',
  5. components: { temptpl }
  6. })

6、渲染结果

  1. <div id="J_vapp">
  2. <p data-v-d0145a06="">hello,vue</p>
  3. </div>

可以看出html中的J_vapp元素不会消失,充当载体桥梁的是temptpl,temptpl最后不会出现在dom中。

六、提取单文件组件的css
1、安装webpack插件

  1. cnpm i -D extract-text-webpack-plugin

2、安装webpack

  1. cnpm i -D webpack

extract-text-webpack-plugin需要webpack作为依赖,npm3不会自动安装依赖。
如果不安装webpack,你会看到报错,Cannot find module 'webpack/lib/Chunk'。
3、配置webpack.config.js

  1. var ExtractTextPlugin = require("extract-text-webpack-plugin");
  2. module.exports = {
  3. entry: './main.js',
  4. output: {
  5. path: __dirname,
  6. filename: 'bundle.js'
  7. },
  8. devtool: "inline-source-map",
  9. module: {
  10. rules: [
  11. {
  12. test: /\.vue$/,
  13. loader: 'vue-loader',
  14. options: {
  15. loaders: {
  16. css: ExtractTextPlugin.extract({
  17. use: 'css-loader',
  18. fallback: 'vue-style-loader' //这是vue-loader的依赖,所以如果使用npm3,则不需要显式安装。
  19. })
  20. }
  21. }
  22. }
  23. ]
  24. },
  25. resolve: {
  26. alias: {
  27. vue$: 'vue/dist/vue.js' //vue$表示精确匹配
  28. }
  29. },
  30. plugins: [
  31. new ExtractTextPlugin("style.css")
  32. ]
  33. }

4、新建index.html

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>提取单文件组件的css</title>
  6. <link rel="stylesheet" type="text/css" href="style.css">
  7. </head>
  8. <body>
  9. <div id="J_vapp">
  10. <temptpl></temptpl>
  11. </div>
  12. <script type="text/javascript" src="bundle.js"></script>
  13. </body>
  14. </html>

5、其他文件
与独立构建的demo中的package.json文件,hello.vue,main.js文件保持一致。

七、提取自定义块
1、安装raw-loader

  1. cnpm i -D raw-loader

2、修改hello.vue文件

  1. <docs>
  2. ## This is an Example component.
  3. </docs>
  4. <template>
  5. <p>{{greeting}},vue</p>
  6. </template>
  7. <script type="text/javascript">
  8. export default {
  9. data:function(){
  10. return {
  11. greeting:"hello"
  12. }
  13. }
  14. }
  15. </script>
  16.  
  17. <style scoped>
  18. p{
  19. font-size:15px;
  20. color:red;
  21. }
  22. </style>

3、配置webpack.config.js文件

  1. var ExtractTextPlugin2 = require("extract-text-webpack-plugin");
  2.  
  3. module.exports = {
  4. entry: './main.js',
  5. output: {
  6. path: __dirname,
  7. filename: 'bundle.js'
  8. },
  9. devtool: "inline-source-map",
  10. module: {
  11. rules: [
  12. {
  13. test: /\.css$/,
  14. use: ['style-loader','css-loader']
  15. },
  16. {
  17. test: /\.vue$/,
  18. loader: 'vue-loader',
  19. options: {
  20. loaders: {
  21. // 提取 <docs> 中的内容为原始文本
  22. 'docs': ExtractTextPlugin2.extract('raw-loader')
  23. }
  24. }
  25. }
  26. ]
  27. },
  28. resolve: {
  29. alias: {
  30. vue$: 'vue/dist/vue.js' //vue$表示精确匹配
  31. }
  32. },
  33. plugins: [
  34. new ExtractTextPlugin2("docs.md")
  35. ]
  36. }

4、疑惑
自定义块是按照期望提取到docs.md中了,但是如果我想把.vue文件中的自定义块提取到docs.md,css提取到style.css,我该怎么办?我尝试实例化两个ExtractTextPlugin,发现提取结果是自定义块和css同时出现在docs.md和style.css中,不是我想要的结果。理想的结果应该是,docs.md只包含自定义块的内容,style.css只包含css的内容。

八、代码检验
eslint-loader能够在开发期间每次保存.vue文件时自动检验js代码规范。

1、安装loader

  1. cnpm i -D eslint eslint-loader eslint-plugin-html

2、修改webpack.config.js文件

  1. module.exports = {
  2. entry: './main.js',
  3. output: {
  4. path: __dirname,
  5. filename: 'bundle.js'
  6. },
  7. devtool: "inline-source-map",
  8. module: {
  9. rules: [
  10. {
  11. enforce: 'pre',
  12. test: /\.(js|vue)$/,
  13. loader: 'eslint-loader',
  14. exclude: /node_modules/
  15. },
  16. {
  17. test: /\.vue$/,
  18. loader: 'vue-loader'
  19. },
  20. {
  21. test: /\.css$/,
  22. use: ['style-loader','css-loader']
  23. }
  24. ]
  25. },
  26. resolve: {
  27. alias: {
  28. vue$: 'vue/dist/vue.js' //vue$表示精确匹配
  29. }
  30. }
  31. }

Webpack loader处理顺序是从右到左。确保在vue-loader之前应用eslint-loader,这样才能检验编译前的代码。webpack中所有的loader都可以拥有include和exclude属性,exclude排除不满足条件的文件夹,include匹配需要被loader处理的文件或文件夹。第三方的.vue组件可以不用检验,只检验自己写的。
3、修改package.json文件

  1. {
  2. "name": "vuetest",
  3. "version": "1.0.0",
  4. "description": "",
  5. "scripts": {
  6. "test": "echo \"Error: no test specified\" && exit 1",
  7. "server": "webpack-dev-server --open",
  8. "build": "webpack-dev-server"
  9. },
  10. "author": "camille",
  11. "license": "ISC",
  12. "devDependencies": {
  13. "css-loader": "^0.28.7",
  14. "eslint": "^4.9.0",
  15. "eslint-loader": "^1.9.0",
  16. "eslint-plugin-html": "^3.2.2",
  17. "style-loader": "^0.19.0",
  18. "vue": "^2.5.2",
  19. "vue-loader": "^13.3.0",
  20. "vue-template-compiler": "^2.5.2"
  21. },
  22. "eslintConfig": {
  23. "env": {
  24. "browser": true
  25. },
  26. "plugins": [
  27. "html"
  28. ]
  29. }
  30. }

4、新建index.html

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>代码检查eslint,.vue文件和js文件</title>
  6. </head>
  7. <body>
  8. <div id="J_vapp"></div>
  9. <script type="text/javascript" src="bundle.js"></script>
  10. </body>
  11. </html>

5、修改main.js文件

  1. var Vue = require('vue')
  2. var temptpl = require('./hello.vue').default
  3.  
  4. var vm = new Vue({
  5. el: '#J_vapp',
  6. template:'<tpl/>',
  7. components: { tpl: temptpl }
  8. })

6、新建hello.vue文件

  1. <template>
  2. <p>{{greeting}},vue</p>
  3. </template>
  4. <script type="text/javascript">
  5. module.exports={
  6. data:function(){
  7. return {
  8. greeting:"hello"
  9. }
  10. }
  11. }
  12. </script>
  13.  
  14. <style scoped>
  15. p{
  16. font-size:15px;
  17. color:red;
  18. }
  19. </style>

7、测试
故意写个错误,看看eslint-loader会不会起作用。
8、渲染结果

  1. <p data-v-17976ece>hello,vue</p>

可以看出html中的J_vapp相当于桥梁,最后不会出现在dom中。

vue中的单文件组件的更多相关文章

  1. Vue中创建单文件组件 注册组件 以及组件的使用

    <template> <div id="app"> <v-home></v-home> <hr > <br> ...

  2. vue入门之单文件组件

    介绍 在很多 Vue 项目中,我们使用 Vue.component 来定义全局组件,紧接着用 new Vue({ el: '#container '}) 在每个页面内指定一个容器元素. 这种方式在很多 ...

  3. Vue -3:单文件组件

    在很多 Vue 项目中,我们使用 Vue.component 来定义全局组件,紧接着用 new Vue({ el: '#container '}) 在每个页面内指定一个容器元素. 这种方式在很多中小规 ...

  4. 如何在vue && webpack 项目中的单文件组件中引入css

    引入方式很简单,就是在script下使用require()即可. 因为import 是import...from 的形式,所以是不需要的. <script> import {mapStat ...

  5. 【原】vue单文件组件互相通讯

    在vue中,我们可以把一个页面各个部分单独封装起来,做成各种小组件,然后加载,这样的好处是代码维护起来比较容易,重复的代码多处调用! 在一个vue项目中,单文件组件以.vue形式文件命名 每个组件之间 ...

  6. vue单文件组件互相通讯

    在vue中,我们可以把一个页面各个部分单独封装起来,做成各种小组件,然后加载,这样的好处是代码维护起来比较容易,重复的代码多处调用! 在一个vue项目中,单文件组件以.vue形式文件命名 每个组件之间 ...

  7. vue中创建全局单文件组件/命令

    1.在 vue中如果我们使用基于vue.js编写的插件,我们可以使用Vue.use() 如在main.js中: 2.添加全局命令,让每个vue单文件组件都可以使用到: 第一步:最好建一个全局的命令文件 ...

  8. vue 单文件组件中样式加载

    在写单文件组件时,一般都是把标签.脚本.样式写到一起,这样写个人感觉有点不够简洁,所以就想着把样式分离出去. 采用import加载样式 在局部作用域(scoped)采用@import加载进来的样式文件 ...

  9. webpack入坑之旅(五)加载vue单文件组件

    这是一系列文章,此系列所有的练习都存在了我的github仓库中vue-webpack,在本人有了新的理解与认识之后,会对文章有不定时的更正与更新.下面是目前完成的列表: webpack入坑之旅(一)不 ...

随机推荐

  1. 弹框勾选datatable中的数据,点击保存后添加到另一个表中,同一个页面

    需求描述:做编辑的时候,点击添加按钮,弹出数据表table2,勾选弹出框中的数据,点击保存后能够添加到table1中,并且已经被添加到table1中的数据,在弹出框中显示已选,checkbox隐藏:t ...

  2. 基于BootStrap的Collapse折叠(包含回显展开折叠的对应状态)

    情况描述:为了改善页面上的input框太多,采用∧∨折叠展开,这个小东西来控制,第一次做,记录一下ヾ(◍°∇°◍)ノ゙下边是Code 代码: //html代码 <div id="col ...

  3. DOBRI

    问题 : DOBRI 时间限制: 1 Sec  内存限制: 128 MB 题目描述 给出一个包含N个整数的序列A,定义这个序列A的前缀和数组为SUM数组 ,当SUM数组中的第i个元素等于在i前面的三个 ...

  4. Python交换a,b两个数值的三种方式

    # coding:utf-8 a = 1 b = 2 # 第一种方式 # t = a # 临时存放变量值 # a = b # b = t # 第二种方式 # a = a + b # a的值已经不是原始 ...

  5. 总结Java虚拟机内存区域模型

    本篇文章主要来总结一下Java虚拟机内存的各个区域,以及这些区域的作用.服务对象以及其中可能产生的问题,作为大家的面试宝典. 首先我们来看一下Java运行时的数据区域,Java虚拟机在执行Java程序 ...

  6. Centos7搭建dhcp服务器

    实验拓扑: 实验步骤如下: 1.挂载本地镜像,并安装dhcp组件. 2.更改配置文件,并重启服务. . 3.配置dhcp地址池范围 4.配置防火墙 结果:在客户端上,重启网卡,后查看ip

  7. 手机网页制作教程META标签你知道多少?【转+加】

    一.天猫 <title>天猫触屏版</title> <meta content="text/html; charset=utf-8" http-equ ...

  8. 【C++ Primer | 10】泛型算法

    #include<iostream> #include<algorithm> #include<vector> #include<string> #in ...

  9. python--使用递归优雅实现列表相加和进制转换

    咦,好像坚持了一段时间,感觉又有新收获啦. # coding: utf-8 class Stack: def __init__(self): self.items = [] # 是否为空 def is ...

  10. mysql 一张表的多个字段关联另外一张表

    SELECT vtiger_orderitem.orderid, ( SELECT vtiger_users.last_name FROM vtiger_users WHERE vtiger_orde ...