学习使用webpack+vue搭建项目
最近,一直把JS基本语法知识重新巩固学习的同时,也一直在跟着上篇文章中提到的名为“守候”的博主发表的文章进行学习,今天也将自己在通过他的文章使用webpack+vue搭建项目环境的过程中遇到的值得记录的点,都一并写在这里。
仅仅自己目前对webpack的理解,就是一个打包工具。可以将项目中不同的语言识别转换成js,从设定的入口文件找到项目的所有依赖文件,将项目模块化开发,最终打包为一个或者多个浏览器可以识别的JavaScript文件。更深层次的还没有进一步理解,不过在操作过程中对其使用有更进一步的理解。
一、基本环境的安装配置及使用如下:
1. 首先,安装webpack,建议先全局安装后再安装到本地目录,具体的原因目前自己没有深入理解。
npm install -g webpack //全局安装
npm install --save-dev webpack
2 . 在package.json中,对项目描述信息及项目所需要使用到的相关依赖进行添加。可以手动创建或通过命令行:npm init。
3.webpack配置文件的完成:指定入口文件、出口文件、加载器及 插件等。
//基本上就差不多了,需要使用的Vue、element-ui等,按照官方文档说明安装即可。
4.router.js配置
5.入口文件和入口文件模板的配置。
具体的直接参照该博主的系列文章:webpack+vue项目实战(一,搭建运行环境和相关配置)。
6.!!需要注意的点:
(1)由于博主是之前记录的,webpack、element-ui的版本都和现在有所偏差。可能很多小伙伴都运行报错,我也是一样,将版本升级后,再修改对应的配置即可。没有截图记录我当时的报错原因,反正报错后,我将所有的东西都升到了最新版,另外在入口文件中引入element-ui的css样式时,其默认的文件名已经由theme-default——>改为了theme-chalk。修改完毕后,运行成功。
(2)如下图所示,突然发现,哎哟~为什么路由路径是在dist目录下呢?而且我们的文件中并没有这个路径。
这就让我有点疑惑了,为什么它的指定路径会在dist/html下呢?而之前我接触到的项目都是直接locahost:端口号就可直接运行了,这里这样运行却会报错。
原因就是我们用了webpack-dev-server构建生成的包,实际是放在内存中的,即这里前面的前缀是代表虚拟目录,因此我们看不到编译后的dist文件。查询webpack-dev-server的定义:
webpack-dev-server是一个小型的node.js Express服务器,它使用webpack-dev-middleware中间件来为通过webpack打包生成的资源文件提供Web服务。
我想大概比较明朗了,因为我们设置webpack的输出路径:
output: {
path: path.join(__dirname, 'dist'), /*输出目录的配置,模板、样式、脚本、图片等资源的路径配置都相对于它*/
publicPath: '/dist/',
filename: 'js/[name].js',
chunkFilename: 'js/[name].asyncChunk.js?'+new Date().getTime() //chunk生成的配置
},
而且对npm也进行了设置,可通过简单的命令运行webpack-dev-server,且设置为热加载,方便修改后自动重新加载更新效果。
上面代码中涉及到的:
__dirname变量值代表程序运行的根目录;
path.join:路径合并 // 特点: 将多个路径名称用path.seq串联起来,然后normalize格式化
./ //当前目录下
../ //父级目录
/ //根目录
例如:
path.join('//foo','bar','//baz/dfj'); // --> '/foo/bar/baz/dfj'
关于node.js中path对象更多的用法,可参考xiaobing_hope博主的文章”Node.js的Path对象“,里面有比较详细的说明哟。
另外,之所以之前我的项目中直接输入localhost:端口号/#就可以的原因是,之前的项目重新书写了webpack-dev-server,并没有直接使用下载的。
然后也配置了npm命令的简单方式:
上图表示打包文件的输出位置为build文件夹下的根目录。
简而言之,如果直接下载安装,我们在线运行webpack-dev-server时打包的文件在内存中,但我们可以通过自己实现dev-server对其进行改写后,实现自己想要的效果,如打包文件放置位置及可编译及编译文件生成的位置……
(3)在浏览时,发现博主用click点击事件时,还用到了Vue.js的stop修饰符,这个是用来防止冒泡事件的发生的。冒泡事件简而言之就是当前事件的传播性,防止影响到其他事件。
、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、
注意点的第二条,感觉自己理解乱七八糟的,可能很多地方都存在着错误,但还是记录下来当前的理解,我希望通过自己不断的学习能回过头发现自己的错误并改正。小伙伴们看到不对,务必一定指出来,非常感谢!我想,积累是一个从无到有的过程。
二、开发管理系统主页面
基于第一部分已经搭建好的环境,我也跟随着博主的脚步去动手实现一个管理系统。因为之前都是直接用的Vue.js的脚手架生成生成,因此默认的项目结构是固定的,如下图所示。直接输入localhost:8080会看到vue的图标界面。
现在直接借助webpack自己写配置文件也能实现同样的效果,动手试试也是很不错的。而且博主的文件放置非常清晰,根目录下就是安装的依赖文件夹node_modules、源文件夹src用于存放有效实现代码、下面的package.json及webpack.config.babel.js当然就是配置文件啦。
js文件夹下的目录结构如下图所示:
而页面组件下又将主页面和其他页面组件分开放置在不同文件夹中,并且主页面也将不同的功能实现代码都分开放置了,如下图所示。这样修改时能很方便的修改某个部分。
1.顶部组件栏实现
直接在componets文件夹下新建一个toopbar.vue文件,简单的写一点东西就可以。然后在入口文件index.js中引入这个文件并在vue中注册:
最后,在入口模块文件index.html中直接使用注册的组件名为标签使用就可以了。
2.侧边栏的实现
我就直接element-ui中的导航菜单配合router实现简要地实现了该效果。操作同上面顶部组件栏实现一致,不过是在页面上实现的内容不同而已。注意switch语句中的判断条件可以为任何类型,但是此处为字符串一定呀加上字符串,最开始我就没有加,找了好久的错误。。。。
好了,主要的实现原理就是这样子,通过菜单项切换到不同的路由界面下,我们仍旧类似的实现方法,只要写好了,在路由引入后里配置相应的路径和组件即可。原理就是,当我们输入主界面的url时,通过router.js中路由匹配到主界面,当点击菜单选择菜单项后,又是触发了路由跳转到不同的界面,简单的界面交互就是这样啦。更具体的实现,不清楚的时候可以去看看该博主的原文,写的更加的详细一点,描述也比我有逻辑T T。
三、按需加载
“当打包构建应用时,Javascript包会变得非常大,影响页面的加载。如果我们能把不同路由对应的组件分割成不同的代码块,然后当路由被访问时加载对应组件,这样就更加高效了。”这是Vue.js的官方文档中路由懒加载部分的原文,因此这里我们也可以将路由下的所有组件都打包在同个异步块中,使用命名chunk来提供chunk name(Webpack>2.4),对路由来个“懒加载”。
四、多个菜单项共用同一页面(根据路由不同,呈现不同的效果内容)
1.首先在router.js里配置。这里用到了动态路由匹配,参考资料Vue官方文档:动态路由匹配。
2.在菜单匹配处传递参数:
selectMenu:function(key, keyPath){
switch(key){
case '1':this.$router.push('/index');break;
case '2-1-1':this.$router.push({name:'待确认订单',query:{status:'0'}});break;
case '2-1-3':this.$router.push({path:'/sale/sureList/'/*,name:'订单管理'*/});break;
}
}
3.在界面处利用watch和mounted()监听路由选择。
实现过程中遇到的问题,this.$route.push()函数的错误使用,具体详见动态路由匹配不成功。这里对问题和解决方法都进行了具体的描述,其中命名路由的使用参照了官方文档动态路由部分:
查看 route.push()用法,发现一般有下面的三种用法(不知道为什么dollar符号不能正确显示,下面调用方法时route前面都有dollar符号的哈),要么只push路径path,要么push name和参数status确定路由。
(1)字符串:
router.push(‘home’)
(2)对象:
router.push({path: ‘/login?url=’ + this.$route.path});
(3)命名的路由,后面的参数为动态路由的参数:
router.push({ name: ‘user’, params: { userId: 123 }})
(4)带查询参数,变成/backend/order?selected=2
trouter.push({path: ‘/backend/order’, query: {selected: “2”}});
五、购物车统计总价页面
同样是跟随该博主的Vue快速入门的三个小实例动手实践,另外自己在实现的时候采用element-ui中的el-table,顺便加深对其的学习理解。果然,看着很简单,实现时也是跳进了不少坑。
分析实现:直接在前面实现的基础上新增加页面,用来完成购物车计算总价功能。整个流程也是差不多布局->数据->操作函数实现。
(1)直接先上“html”代码:
<template>
<el-table ref="multipleTable" :data="tableData3" tooltip-effect="dark" style="width: 100%" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55">
</el-table-column>
<el-table-column label="商品" width="260" prop="product">
<template slot-scope="scope">
<img :src="scope.row.product.pro_img" width="98" height="98">
<div class=‘product-info’>
<h4>{{scope.row.product.pro_name}}</h4>
<p>品牌:{{scope.row.product.pro_brand}}</p>
<p>产地:{{scope.row.product.pro_place}}</p>
<p>规格/纯度:{{scope.row.product.pro_purity}} 起定量:{{scope.row.product.pro_min}}</p>
<p>配送仓储:{{scope.row.product.pro_depot}}</p>
</div>
<div class="clearfix"></div>
</template>
</el-table-column>
<el-table-column prop="pro_num" label="数量" width="200">
<template slot-scope="scope">
<el-input-number v-model="scope.row.pro_num" @change="handleChange" :min="1" :max="10000">
</el-input-number>
</template>
</el-table-column>
<el-table-column prop="pro_price" label="单价(元)" width="170">
</el-table-column>
<el-table-column prop="pro_total" label="金额(元)" width="170">
<template slot-scope="scope">
{{scope.row.pro_num*scope.row.pro_price}}
</template>
</el-table-column>
<el-table-column label="操作" width="100">
<template slot-scope="scope">
<el-button size="mini" type="danger" @click="handleDelete(scope.$index, scope.row)">删除</el-button> </template>
</el-table-column>
</el-table>
<div style="margin-top: 20px">
</div>
</template>
上面利用el-table自定义列模板,组合其他的组件使用,分别用表格列来代表商品信息、数量、单价等,表格项中又插入其他的块,不是直接的数据。使用了scoped slot,这个可以获取到row,column,$index和store(table内部的状态管理)的数据,用法参考官方demo及本例。
!!!!!要注意数量列的数据绑定的方法,v-model值和prop的属性绑定!!!
及后面总金额数量的改变,直接在前面利用{{ scope.row.pro_num*scope.row.pro_price}}调用到当前操作的数据项的单价数量。
(2)js部分:
export default{
data() {
return {
tableData3: [{
product:{
pro_name: '【斯文】甘油 | 丙三醇',
pro_brand: 'skc',
pro_place:'韩国',
pro_purity: '99.7%',
pro_min:'215千克',
pro_depot:'上海仓海仓储',
pro_img:''
},
pro_price:'800',
pro_num:'1',
pro_total:'800'
}],
multipleSelection: []
}
},
methods: {
//智能的全选判断
toggleSelection(rows) {
if (rows) {
rows.forEach(row => {
this.$refs.multipleTable.toggleRowSelection(row);
});
} else {
this.$refs.multipleTable.clearSelection();
}
},
//当前的选中项及个数,可方便对选中项进行操作,不写也没得关系。
handleSelectionChange(val) {
this.multipleSelection = val;
console.log(this.multipleSelection);
},
//数量计数器改变值时触发的函数
handleChange(){
}
}
}
js部分主要是给了table数据,及全选函数及计数函数简单实现,没有做复杂的限制。toggleSelection直接是原demo实现,原谅我直接使用了,没有仔细研究其递归原理。最后也实现了博主那样的效果哟,哈哈。下面图1是勾选函数的打印结果,图二是最终的效果。
图1
图2
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
(3)实现过程中,犯的错误和踩得坑也不少。
将总价金额用另一种方式计算,利用计数器改变时触发的函数:
//下面的value = scope.row
handleChange(value){
console.log(value);
console.log(value.pro_num);
console.log(value);
value.pro_total = value.pro_num * value.pro_price;
}
结果发现初态:
图3
点击添加按钮后,计数器变为2,获取的scope.row对象中num=2,但是!!只要我们通过对象单独引用pro_num的值时,他的值就变了,始终是变化前一次的值。如下图4所示:
图4
不知道为什么会这样,不过在使用elment-ui其他组件过程中,如多选框,其中的change函数也存在类似的问题,获取到的始终是改变前的上一轮值,不能实时获取最新情况。有可耐的小伙伴知道,求告知,感激不尽!
图5
上面图5是在copy跑博主的小实例选项卡原码中遇到的问题,绑定属性时,错误的将:放到了引号内,所以一直报错。不过这种写法以前也是没有尝试过,又学到了一招哈哈。切换选择不同的项是,当前选中项即激活状态显示同一个颜色,就必然共用同一样式,不过样式的显示这样显示可以说是非常机智了,已get。
六、todolist
也就是博主的Vue快速入门的三个小实例中的最后一个实例。实现过程中,依葫芦化瓢,照着博主的步骤及代码,手动敲代码,试图理解透每一点。实现中,没有使用其他的插件,页面均用原生的html标签实现,也顺道温习。然鹅,我还是遇到了目前还未找出的bug及不理解的css样式。
1.先简单记录下不熟的点:
单选框或者输入框,均用input,只是据情况设置type,且单选框的选择事件用click触发;
键盘的输入状态触发:
keyup.13 keyup.enter–>回车键
keyup.esc –>返回键
dbclick –>双击
2.问题及bug:
(1)????关于获取到当前鼠标放置位置,删除按钮X的显示????????
li .close{
position: absolute;
color: #f00;
font-size: 20px;
line-height: 40px;
height: 40px;
right: 20px;
cursor: pointer;
display: none;
top: 0;
}
li:hover .close{display: block;} //为什么设置为块元素时才显示,否则就看不到X!!
li .text-keyword{
height: 40px;
padding-left: 10px;
box-sizing: border-box;
margin-left: 10px;
width: 80%;
display: none;
}
去掉那句后,检查元素,还是看不到
(2)双击事件不起作用!导致不能修改原有的列表信息。
版权声明:本文为博主Bonjourjw(http://blog.csdn.net/bonjourjw)原创文章,未经博主允许不得转载。