vue中的单文件组件
之前都是在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文件
{ "name": "vuetest", "version": "1.0.0", "description": "", "scripts": { "test": "echo \"Error: no test specified\" && exit 1", "server": "webpack-dev-server --open", "build": "webpack-dev-server" }, "author": "camille", "license": "ISC", "devDependencies": { "css-loader": "^0.28.7", "style-loader": "^0.19.0", "vue": "^2.5.2", "vue-loader": "^13.3.0", "vue-template-compiler": "^2.5.1" } }
2、新建webpack.config.js文件
module.exports = { entry: './main.js', output: { path: __dirname, filename: 'bundle.js' }, devtool: "inline-source-map", module: { rules: [ { test: /\.vue$/, loader: 'vue-loader' }, { test: /\.css$/, use: ['style-loader','css-loader'] } ] } }
3、新建index.html文件
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>单文件组件运行时构建</title> </head> <body> <div id="J_vapp"></div> <script type="text/javascript" src="bundle.js"></script> </body> </html>
4、新建hello.vue单文件组件
<template> <p>{{ greeting }},vue</p> </template> <script> module.exports={ data:function(){ return { greeting:"hello" } } } </script> <style scoped> p{ font-size:15px; color:red; } </style>
5、新建main.js文件
import Vue from 'vue' import sfile from './hello.vue' var vm = new Vue({ el: '#J_vapp', render: function(h){ return h(sfile) } })
6、渲染结果
<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文件
var Vue = require('vue') var sfile = require('./hello.vue') var vm = new Vue({ el: '#J_vapp', render: function(h){ return h(sfile) } })
紧接着出现“Vue is not a constructor”问题。
2、修改webpack.config.js文件
module.exports = { entry: './main.js', output: { path: __dirname, filename: 'bundle.js' }, devtool: "inline-source-map", module: { rules: [ { test: /\.vue$/, loader: 'vue-loader' }, { test: /\.css$/, use: ['style-loader','css-loader'] } ] }, resolve: { alias: { vue$: 'vue/dist/vue.js', //vue$表示精确匹配 } } }
前面那个问题解决了,接着又有“Failed to mount component: template or render function not defined.”问题。
3、修改main.js文件
各种探索,终于在vue-loader变更这里找到问题根源,如果依赖了v13+的vue-loader,用require引入.vue文件时,后面加上default。
var Vue = require('vue') var sfile = require('./hello.vue').default var vm = new Vue({ el: '#J_vapp', render: function(h){ return h(sfile) } })
五、独立构建的demo
1、新建package.json文件
同运行时构建。
2、新建webpack.config.js文件
module.exports = { entry: './main.js', output: { path: __dirname, filename: 'bundle.js' }, devtool: "inline-source-map", module: { rules: [ { test: /\.vue$/, loader: 'vue-loader' }, { test: /\.css$/, use: ['style-loader','css-loader'] } ] }, resolve: { alias: { vue$: 'vue/dist/vue.js' //vue$表示精确匹配 } } }
注意:如果没有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文件
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>单文件组件,独立构建,模板命名很重要</title> </head> <body> <div id="J_vapp"> <temptpl></temptpl> </div> <script type="text/javascript" src="bundle.js"></script> </body> </html>
4、新建hello.vue单文件组件
<template> <p>{{greeting}},vue</p> </template> <script type="text/javascript"> export default { data:function(){ return { greeting:"hello" } } } </script> <style scoped> p{ font-size:15px; color:red; } </style>
5、新建main.js文件
import Vue from 'vue' import temptpl from './hello.vue' var vm = new Vue({ el: '#J_vapp', components: { temptpl } })
6、渲染结果
<div id="J_vapp"> <p data-v-d0145a06="">hello,vue</p> </div>
可以看出html中的J_vapp元素不会消失,充当载体桥梁的是temptpl,temptpl最后不会出现在dom中。
六、提取单文件组件的css
1、安装webpack插件
cnpm i -D extract-text-webpack-plugin
2、安装webpack
cnpm i -D webpack
extract-text-webpack-plugin需要webpack作为依赖,npm3不会自动安装依赖。
如果不安装webpack,你会看到报错,Cannot find module 'webpack/lib/Chunk'。
3、配置webpack.config.js
var ExtractTextPlugin = require("extract-text-webpack-plugin"); module.exports = { entry: './main.js', output: { path: __dirname, filename: 'bundle.js' }, devtool: "inline-source-map", module: { rules: [ { test: /\.vue$/, loader: 'vue-loader', options: { loaders: { css: ExtractTextPlugin.extract({ use: 'css-loader', fallback: 'vue-style-loader' //这是vue-loader的依赖,所以如果使用npm3,则不需要显式安装。 }) } } } ] }, resolve: { alias: { vue$: 'vue/dist/vue.js' //vue$表示精确匹配 } }, plugins: [ new ExtractTextPlugin("style.css") ] }
4、新建index.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>提取单文件组件的css</title> <link rel="stylesheet" type="text/css" href="style.css"> </head> <body> <div id="J_vapp"> <temptpl></temptpl> </div> <script type="text/javascript" src="bundle.js"></script> </body> </html>
5、其他文件
与独立构建的demo中的package.json文件,hello.vue,main.js文件保持一致。
七、提取自定义块
1、安装raw-loader
cnpm i -D raw-loader
2、修改hello.vue文件
<docs> ## This is an Example component. </docs> <template> <p>{{greeting}},vue</p> </template> <script type="text/javascript"> export default { data:function(){ return { greeting:"hello" } } } </script> <style scoped> p{ font-size:15px; color:red; } </style>
3、配置webpack.config.js文件
var ExtractTextPlugin2 = require("extract-text-webpack-plugin"); module.exports = { entry: './main.js', output: { path: __dirname, filename: 'bundle.js' }, devtool: "inline-source-map", module: { rules: [ { test: /\.css$/, use: ['style-loader','css-loader'] }, { test: /\.vue$/, loader: 'vue-loader', options: { loaders: { // 提取 <docs> 中的内容为原始文本 'docs': ExtractTextPlugin2.extract('raw-loader') } } } ] }, resolve: { alias: { vue$: 'vue/dist/vue.js' //vue$表示精确匹配 } }, plugins: [ new ExtractTextPlugin2("docs.md") ] }
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
cnpm i -D eslint eslint-loader eslint-plugin-html
2、修改webpack.config.js文件
module.exports = { entry: './main.js', output: { path: __dirname, filename: 'bundle.js' }, devtool: "inline-source-map", module: { rules: [ { enforce: 'pre', test: /\.(js|vue)$/, loader: 'eslint-loader', exclude: /node_modules/ }, { test: /\.vue$/, loader: 'vue-loader' }, { test: /\.css$/, use: ['style-loader','css-loader'] } ] }, resolve: { alias: { vue$: 'vue/dist/vue.js' //vue$表示精确匹配 } } }
Webpack loader处理顺序是从右到左。确保在vue-loader之前应用eslint-loader,这样才能检验编译前的代码。webpack中所有的loader都可以拥有include和exclude属性,exclude排除不满足条件的文件夹,include匹配需要被loader处理的文件或文件夹。第三方的.vue组件可以不用检验,只检验自己写的。
3、修改package.json文件
{ "name": "vuetest", "version": "1.0.0", "description": "", "scripts": { "test": "echo \"Error: no test specified\" && exit 1", "server": "webpack-dev-server --open", "build": "webpack-dev-server" }, "author": "camille", "license": "ISC", "devDependencies": { "css-loader": "^0.28.7", "eslint": "^4.9.0", "eslint-loader": "^1.9.0", "eslint-plugin-html": "^3.2.2", "style-loader": "^0.19.0", "vue": "^2.5.2", "vue-loader": "^13.3.0", "vue-template-compiler": "^2.5.2" }, "eslintConfig": { "env": { "browser": true }, "plugins": [ "html" ] } }
4、新建index.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>代码检查eslint,.vue文件和js文件</title> </head> <body> <div id="J_vapp"></div> <script type="text/javascript" src="bundle.js"></script> </body> </html>
5、修改main.js文件
var Vue = require('vue') var temptpl = require('./hello.vue').default var vm = new Vue({ el: '#J_vapp', template:'<tpl/>', components: { tpl: temptpl } })
6、新建hello.vue文件
<template> <p>{{greeting}},vue</p> </template> <script type="text/javascript"> module.exports={ data:function(){ return { greeting:"hello" } } } </script> <style scoped> p{ font-size:15px; color:red; } </style>
7、测试
故意写个错误,看看eslint-loader会不会起作用。
8、渲染结果
<p data-v-17976ece>hello,vue</p>
可以看出html中的J_vapp相当于桥梁,最后不会出现在dom中。
vue中的单文件组件的更多相关文章
- Vue中创建单文件组件 注册组件 以及组件的使用
<template> <div id="app"> <v-home></v-home> <hr > <br> ...
- vue入门之单文件组件
介绍 在很多 Vue 项目中,我们使用 Vue.component 来定义全局组件,紧接着用 new Vue({ el: '#container '}) 在每个页面内指定一个容器元素. 这种方式在很多 ...
- Vue -3:单文件组件
在很多 Vue 项目中,我们使用 Vue.component 来定义全局组件,紧接着用 new Vue({ el: '#container '}) 在每个页面内指定一个容器元素. 这种方式在很多中小规 ...
- 如何在vue && webpack 项目中的单文件组件中引入css
引入方式很简单,就是在script下使用require()即可. 因为import 是import...from 的形式,所以是不需要的. <script> import {mapStat ...
- 【原】vue单文件组件互相通讯
在vue中,我们可以把一个页面各个部分单独封装起来,做成各种小组件,然后加载,这样的好处是代码维护起来比较容易,重复的代码多处调用! 在一个vue项目中,单文件组件以.vue形式文件命名 每个组件之间 ...
- vue单文件组件互相通讯
在vue中,我们可以把一个页面各个部分单独封装起来,做成各种小组件,然后加载,这样的好处是代码维护起来比较容易,重复的代码多处调用! 在一个vue项目中,单文件组件以.vue形式文件命名 每个组件之间 ...
- vue中创建全局单文件组件/命令
1.在 vue中如果我们使用基于vue.js编写的插件,我们可以使用Vue.use() 如在main.js中: 2.添加全局命令,让每个vue单文件组件都可以使用到: 第一步:最好建一个全局的命令文件 ...
- vue 单文件组件中样式加载
在写单文件组件时,一般都是把标签.脚本.样式写到一起,这样写个人感觉有点不够简洁,所以就想着把样式分离出去. 采用import加载样式 在局部作用域(scoped)采用@import加载进来的样式文件 ...
- webpack入坑之旅(五)加载vue单文件组件
这是一系列文章,此系列所有的练习都存在了我的github仓库中vue-webpack,在本人有了新的理解与认识之后,会对文章有不定时的更正与更新.下面是目前完成的列表: webpack入坑之旅(一)不 ...
随机推荐
- Penetration testing _internal & wireless Penetration Testing
第一部分 渗透测试步骤 ---参考资料 Ethical Hacking: The Value of Controlled Penetration Tests 下载地址 链接:https://pa ...
- poj2836 状态压缩dp
自己的做法是枚举i,j作为顶点的矩形,然后再更新状态S,但是这种做法是错误的 正解是先把所有矩形对求出来,然后枚举状态S,每个处理每个状态时再枚举已经求出的矩形对,用旧状态更新新状态 #include ...
- C++ shut down a computer
前阵子有朋友问我,怎么用C语言写一个小程序,控制电脑关机.这个我真的不懂,这几天闲着,就上网搜了搜,整理一下. IDE: Code::Blocks 16.01 操作系统:Windows 7 x64 # ...
- C++ Primer 笔记——类
1.定义在类内部的函数是隐式的inline函数. 2.因为this的目的总是指向“这个”对象,所以this是一个常量指针,我们不允许改变this中保存的地址. 3.常量成员函数:允许把const关键字 ...
- Android 第二波
三面,4个技术人员面试的问题不是很难.问题如下: 1. Service两种方式的区别 首先说service分为两种,一种是绑定的一种是非绑定的非绑定的生命周期是 onCreate(),onStartC ...
- Ubuntu下创建桌面快捷方式(以Pycharm为例)
之后要在Ubuntu虚拟机上玩PyTorch,安装了Pycharm. 然而每次打开Pycharm需要在其bin目录下进入终端,然后输入sh pycharm.sh,很麻烦.既然Ubuntu是桌面系统,为 ...
- 学习笔记: 特性Attribute详解,应用封装
/// /// 特性:中括号声明 /// /// 错觉:每一个特性都可以带来对应的功能 /// /// 实际上特性添加后,编译会在元素内部产生IL,但是我们是没办法直接使用的, /// 而且在meta ...
- GIT 数据结构
Git doesn’t think of or store its data this way. Instead, Git thinks of its data more like a series ...
- Tarjan算法【强连通分量】
转自:byvoid:有向图强连通分量的Tarjan算法 Tarjan算法是基于对图深度优先搜索的算法,每个强连通分量为搜索树中的一棵子树.搜索时,把当前搜索树中未处理的节点加入一个堆栈,回溯时可以判断 ...
- du -h排序
du -sh * du -s /tmp/*|sort -nr|head -3