分享web开发知识

注册/登录|最近发布|今日推荐

主页 IT知识网页技术软件开发前端开发代码编程运营维护技术分享教程案例
当前位置:首页 > 教程案例

[转] Vue + Webpack 组件式开发(练习环境)

发布时间:2023-09-06 02:21责任编辑:蔡小小关键词:Web组件

前言

研究了下别人的vue多页面框架, 都是直接复制package.json文件,然后在本地npm install一下即可, 或者使用官网vue-cli工具生成一个项目, 觉得这样虽然看的懂, 但是记不住, 因此有必要从零开始搭建一个使用.vue作为组件的项目练习一下, 因此有了这个项目.

既然使用了.vue组件, 就不能像之前使用jQuery一样把vue.js引入页面中, 而是使用配套的webpack+babel+ 各种loader工具编译.vue文件, 再打包生成html.

FBI warning

切记: 因为是最基本的初体验, 所以一些正式开发中必装的loaderplugin就没有装, 因为只是想按照官方教程手动敲出来加深印象, 特别是进阶教程中比较麻烦的父子组件传参, 作用域插槽, 递归组件以及slot等. 因此这个配置不可能作为正式开发的参照配置, 只可作为了解vue组件工作原理的练手项目.

配置说明

以下配置的详细说明在后面可以找到, 不想看的话直接复制下面的package.json即可, 但是为了加深印象还是建议手动敲一遍.

废话不多说, 开始.

首先, 既然是webpack+vue, 那相应的安装包少不了, 这里我们使用vue@2.2.4webpack@1.12.2:

npminstallwebpack@1.12.2vue@2.2.4--save-dev

然后是babel和相应的loader, 这里我们使用es2015这个配置, 用最新的就好:

npminstallbabelbebel-corebabel-loaderbabel-preset-es2015--save-dev

然后是webpack的必装loader,css-loader用来处理cssurl()的资源,style-loader用来将requirecss抽出放到style标签中, 然后加到页面head部分.html-webpack-plugin用来将入口文件js变成html, 入口文件中的各种资源由各种loader处理后插入到它生成的html中,extract-text-webpack-plugin用来将被js通过style标签appendhead中的样式抽出到单独的.css文件中:

npminstallcss-loaderstyle-loaderhtml-webpack-pluginextract-text-webpack-plugin@1.0.1--save-dev

然后是vue相关的东西, 因为一个.vue里面有至少有三个标签template/style/script, 因此需要三个loader来处理, 再加上一个总的vue-loader, 就是四个loader,这里:

vue-html-loaderwebpack的官方html-loaderfork, 作者放到这里只是为了能在webpack.config.js中的module.export.vue对象上使用html选项来单独配置vue的 相关html(本项目安装vue-loader即可, 这里只是顺带安装说明一下);

vue-style-loader用来处理.vue文件中style中的内容, 是webpack的官方style-loaderfork(本项目安装vue-loader即可, 这里只是顺带安装说明一下);

vue-template-compiler用来处理.vue文件中template中的内容, 除非是用它编译后的文件做其他事情才需要单独配置(即写build tools, 否则这个不是必须的, 因为vue-loader已经默认使用它了)(本项目安装 vue-loader 即可, 这里只是顺带安装说明一下);

vue-loader用来处理.vue后缀的内容, 在遇到相关的内容时, 会调用上述三个相关的loader来处理.

npminstallvue-html-loadervue-loadervue-style-loadervue-template-compiler--save-dev

最后就是开发用的webpack-dev-server, 这里我们安装1.12.1版本:

npminstallwebpack-dev-server--save-dev

下面是总的package.json配置文件, 而具体的每个package.json字段的含义, 可以查看这个网站,

{"name":"vue-components","version":"0.0.1","description":"vue components test","main":"app/app.js","scripts":{"dev":"webpack-dev-server --hot","build":"webpack"},"keywords":["vue","components"],"author":"xheldon","license":"MIT","dependencies":{"vue":"^2.2.4"},"devDependencies":{"babel":"^6.23.0","babel-core":"^6.24.0","babel-loader":"^6.4.1","babel-preset-es2015":"^6.24.0","css-loader":"^0.27.3","extract-text-webpack-plugin":"^1.0.1","html-webpack-plugin":"^2.28.0","style-loader":"^0.16.0","vue-html-loader":"^1.2.4","vue-loader":"^11.3.1","vue-style-loader":"^2.0.4","vue-template-compiler":"^2.2.4","webpack":"^1.12.2","webpack-dev-server":"^1.12.1"}}

项目说明

Ok, 依赖安装完了, 接下来看下webpack配置, 因为是想尽快测试vue官方文档的组件部分, 所以一切从简了:

varpath=require(‘path‘);varwebpack=require(‘webpack‘);varHtmlwebpackPlugin=require(‘html-webpack-plugin‘);// 常用配置,项目较小不抽出了varROOT_PATH=path.resolve(__dirname);//根路径varAPP_PATH=path.resolve(ROOT_PATH,‘app‘);//开发路径varBUILD_PATH=path.resolve(ROOT_PATH,‘build‘);//输出路径varExtractTextPlugin=require(‘extract-text-webpack-plugin‘);module.exports={entry:{app:path.resolve(APP_PATH,‘app.js‘)},output:{path:BUILD_PATH,filename:‘bundle.js‘//因为只有一个入口文件, 因此直接写死了},resolve:{alias:{//注意, 这里导入的是/node_module/vue/dist/vue.js, 跟 vue-router.js 的不同vue:‘vue/dist/vue.js‘}},//开启 dev source mapdevtool:‘eval-source-map‘,//开启 dev serverdevServer:{historyApiFallback:true,hot:true,//HMRinline:true,progress:true},module:{loaders:[{test:/\.vue$/,loader:‘vue‘},{test:/\.css$/,loader:ExtractTextPlugin.extract(‘css-loader‘)},{test:/\.js$/,loader:‘babel‘,include:ROOT_PATH,exclude:/node_modules/},{test:/\.html$/,loader:‘vue-html‘}]},vue:{loaders:{css:ExtractTextPlugin.extract(‘css-loader‘)}},plugins:[newHtmlwebpackPlugin({title:‘Vue component test‘,filename:‘this_is_final_filename_address_you_visit_in_browser.html‘,//生成的最终文件名template:‘app/this_is_main_page_which_you_put_components_into.html‘,//放置组件的地方, 一般是一个 body 下一个孤零零的 app 标签即可.inject:true})]};

关于这个配置, 有点东西需要说一下.

从上往下, 首先是alias, 使用过vue-router的人可能不需要这个配置, 但是使用.vue组件的项目必须这个配置,因为需要指定使用的vuejs类型, 看下本项目下node_module/vue/dist/文件夹下的文件, 有vue.jsvue.common.js两种, 其中vue编译template组件的时候是需要一个compiler.js的, 目的是把template中的html内容编译成render函数:

编译前:

<div>Hello</div><script>newVue({el:‘#app‘,data:{who:‘Vue‘}})</script>

编译后:

<div></div><script>newVue({el:‘#app‘,render:function(){with(this){__h__(‘div‘,{staticAttrs:{"id":"app"}},[("\n Hello "+__toString__(who)+"\n")],‘‘)}},data:{who:‘Vue‘}})</script>

vue使用compiler编译template后的js在运行的时候发现有render函数的话就直接执行render,template字段下的内容会被忽略. 而执行编译后的render的任务,是由vue.common.js完成的.因此:

vue.js=vue.common.js+compiler.js

所以, 如果你使用的是vue-router, 它的package.json中的main字段是指向node_module/dist/vue.common.js的, 如果你直接复制这个到你的项目下, 运行的时候会提示你类似于vue.common.jsruntime错误之类的信息.

其次需要说的是这个css-loaderstyle-loader以及vue-style-loader, 有了style-loader为何还要个vue-style-loader呢? 看了下vue-style-loader的说明, 明白了其仅仅是一个style-loaderfork, 但是为了单独处理.vue文件, 同时为了让用户配置vue更清晰, 将其加到了webpack@1.x的配置文件中的vue字段中. 可以通过将extract-text-webpack-plugin插件的配置从:

vue:{loaders:{css:ExtractTextPlugin.extract(‘vue-style-loader‘,‘css-loader‘)}}

改成:

vue:{loaders:{css:ExtractTextPlugin.extract(‘style-loader‘,‘css-loader‘)}}

发现编译后的结果一样证实.

而默认情况下,vue-loader是自动使用vue-style-loader的, 所以如果你不在.vue文件中@import任何css, 那么你不需要手动把vue-loader-style放到vue.loaders字段中.vue-loader会自动处理.vue文件中的style标签中的内容, 并将其放到style标签中插入页面. 而如果你需要在.vue文件中的style标签内@import css文件, 那么你就需要在module.exports.vue单独配置.可以通过把vue字段的vue-style-loader去掉来测试:

module:{loaders:[{test:/\.vue$/,loader:‘vue‘}]},vue:{// loaders: {// css: ‘vue-style-loader!css-loader‘// }}

此外, 入口文件js中的require(‘xxx.css‘)是默认的module.exports.module.loader处理的, 这点可以通过在默认loader中使用extract插件, 而在module.exports.vue中不使用extract插件证实, 因为从结果可以发现, 入口文件中的css被提取了, 但是.vue中的@import来的css没有被提取.

而如果你需要 将入口文件中require来的css文件单独提取出来, 那么你就需要在module.exports.module.loader设置extract-text-webpack-plugin了.

注意:vue-style-loader放在module.exports.vue.loaders字段中是为了能提取出.vue文件中的style标签内容到一个单独的.css文件link在页面中, 把style-loadercss-loader放在默认的module.exports.module.loaders中, 对处理vue中的style标签内容无效————起码在Vue 1.x版本和webpack 1.x版本无效,webpack 2.x版本移除了第三方的字段, 限制在module.export中随意添加字段.

最后,css-loaderstyle-loader总是写在一起的, 因为css-loader的作用是resolve css文件中的@import和 属性值url()中的依赖关系, 单独写其实是没什么用的.style-loader才是处理css, 并将其打包到js中, 最后以<style>标签的形式插入到head(插入位置可配置)中的loader.

最后讲讲extract-text-webpack-plugin, 其接受三个参数:

第一个参数是可选参数, 传入一个loader, 当css样式没有被抽取的时候可以使用该loader. 第二个参数则是用于编译解析的css文件loader, 很明显这个是必须传入的, 就像上述例子的css-loader. 第三个参数是一些额外的备选项, 貌似目前只有传入publicPath, 用于当前loader的路径.

那什么时候需要传入第一个参数呢,那就得明白什么时候样式不会被抽取出来. 了解过code splitting的同学便会知道,我们有些代码在加载页面的时候不会被使用时, 使用code splitting, 可以实现将这部分不会使用的代码分离出去, 独立成一个单独的文件,实现按需加载.

那么如果在这些分离出去的代码中如果有使用require引入样式文件, 那么使用ExtractTextPlugin这部分样式代码是不会被抽取出来的. 这部分不会抽取出来的代码, 可以使用loader做一些处理, 这就是ExtractTextPlugin.extract第一个参数的作用.

OK, 聊完了配置文件, 再说说这个项目是怎么工作的.

一图胜千言, 上图, 首先是代码界面:

(若图片显示较小请在右键在新标签页单独查看)

看箭头所示就明白啦, 首先一个页面是至少有一个组件的, 这个我直接就一个页面一个组件来写了, 没有import其他的组件.

因此, 一个页面下是至少三个文件的,.vue文件,.js入口文件, 和.html, 组件插入的文件.

html中写一个组件app的名字, 入口文件实例化一个vue, 然后使用app这个组件, 同时这个叫做app组件的模板来自index.vue, 组件对应的cssjs以及mvvm的特色:数据绑定也写在index.vue里面.

有同学会疑惑, 入口文件js是怎么找到同目录的html文件的呢? 其实这个在webpack.config.js配置文件就已经写好了:

plugins:[newHtmlwebpackPlugin({title:‘Vue component test‘,filename:‘this_is_final_filename_address_you_visit_in_browser.html‘,//生成的最终文件名template:‘app/this_is_main_page_which_you_put_components_into.html‘,//放置组件的地方, 一般是一个 body 下一个孤零零的 app 标签即可.inject:true})]

这个html生成的插件告诉js入口文件, 所需要的模板来自app下的xxx.html, 而最后打包的bundle.js也是inject这个里面, 再生成最终的页面.

还有同学会问, 在入口js文件中,vue实例化的时候用到的components.App到底是在编译过程就找到了this_is_main_page_which_you_put_components_into.html文件中的<app>组件引用, 还是在runtime的时候, 从最终打包的bundle.js中运行, 然后寻找this_is_final_filename_address_you_visit_in_browser.html页面中的<app>标签呢? 答案是后者, 因为刚才说的HtmlwebpackPlugin插件只负责生成html和注入打包后的bundle.js, 而vue被打包进了bundle.js之后实例化vue时候才会寻找<app>标签.

这么一看, 和直接在script标签中引用vue.js文件再渲染的效果是一样的, 只是webpack这种开发方式帮我们分离了组件, 使开发过程的代码/组件结构更清晰, 而且直接引用vue.js是前端runtime render, 一个是compiler render之后直接执行, 后者效率更高.

之后是效果页面:

(若图片显示较小请在右键在新标签页单独查看)

看图就明白什么意思啦.

还有不明白的请看文档.

[转] Vue + Webpack 组件式开发(练习环境)

原文地址:https://www.cnblogs.com/chris-oil/p/9934229.html

知识推荐

我的编程学习网——分享web前端后端开发技术知识。 垃圾信息处理邮箱 tousu563@163.com 网站地图
icp备案号 闽ICP备2023006418号-8 不良信息举报平台 互联网安全管理备案 Copyright 2023 www.wodecom.cn All Rights Reserved