学习使用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}} &nbsp;&nbsp;起定量:{{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)双击事件不起作用!导致不能修改原有的列表信息。

猜你喜欢

转载自blog.csdn.net/bonjourjw/article/details/78815686