require.js+vue开发微信上传图片组件


Posted in Javascript onOctober 27, 2016

由于项目是thinkPHP做后端框架,一直以来都是多页面的后端路由,想使用火热的webpack有点无从下手(原谅我太菜,而且推广vue只有我一个人……),没办法,想把vue用起来,唯有在原来的基础上改进。使用webpack的巨大好处就是可以使用 .vue 这样的单文件来写vue组件,这样每一个组件就是一个 .vue 文件,哪里用上这个组件就引入进来,维护起来确实很爽。然而一直以来项目用的都是require.js,那又想以这样的形式来组织vue组件,还要加上vue-router和vue-resource,怎么破?这篇文章以开发微信上传图片组件为例子小结一下require.js+vue+vue-router+vue-resource的开发流程。

用require.js组织你的组件
我们会有一个components目录去放我们的各个组件,每个组件有用自己名字命名的文件夹,比如这次的例子album组件,里面就放着这个组件的html、js、css,具体怎样用require.js去加载html和css,大家百度一下把相关插件下载下来即可。于是该组件的js中就可以在define里把相关的依赖都加载进去,最后把组件return出去,别的组件也可以通过define加载这个组件,这也达到了模块化管理组件的目的了。

require.js+vue开发微信上传图片组件

这里的话,我总结了一个使用require.js写vue组件的模板,使用WebStorm把这个模板加上去,每次写组件的时候打几个字就把模板生成出来,不要太爽啊!(componentName是模板的变量,模板生成出来你填上你的组件名字就可以)

define(["vue","text!../js/lib/components/$componentName$/index.html","css!../js/lib/components/$componentName$/index.css"],function (Vue,Template) {
 // 这里是模块的代码
 var $componentName$ = Vue.extend({
  template : Template,
  props : [],
  data : function() {
   return {

   }
  },
  // 在编译结束和 $el 第一次插入文档之后调用
  ready : function() {

  },
  // 在开始销毁实例时调用。此时实例仍然有功能。
  beforeDestroy : function() {

  },
  methods : {

  },
  events : {

  }
 });
 return $componentName$;
});

总体预览这个例子
为了演示完整的流程,我把这个例子做成一个小单页叫show-album,就两个页面:
1.主页叫main-page

require.js+vue开发微信上传图片组件

2.详情页叫detail-page

require.js+vue开发微信上传图片组件

详情页里的功能有:

接收父组件传过来的参数进行上传图片组件的初始化
点击每张图片右上角的叉叉可以删除图片
点击最后那个小相机图案调用微信”从手机相册中选图接口”,用户可以在自己手机上选图
选完图片后,图片按比例调整尺寸变成如图所示那样的缩略图
点击相应的图片调用微信“预览图片接口”进行图片预览
当图片等于最大图片数时,最后那个小相机图案消失
暴露出两个方法供别的组件调用①上传图片方法(上传到微信服务器并执行上传成功后的回调)uploadImage ②获取所有图片信息方法,包括初始化相册、删除过的、新增的图片信息getAllImgInfo

OK,介绍完毕,现在正式开始!

一.使用vue-router做路由,搭建show-album.js
整个功能叫show-album,所以这个功能的js我们就改名为show-album.js,这个js的结构是这样:

define(["vue","vueResource","vueRouter","vAlbum"],function (Vue,VueResource,VueRouter,Album) {
  // 安装资源模块
  Vue.use(VueResource);
  // 安装路由模块
  Vue.use(VueRouter);
  // jquery在执行post请求时,会设置Content-Type为application/x-www-form-urlencoded,
  // 所以服务器能够正确解析,而使用原生ajax请求时,如果不显示的设置Content-Type,那么默认是text/plain,
  // 这时服务器就不知道怎么解析数据了,所以才只能通过获取原始数据流的方式来进行解析请求数据。
  // 由于vue是使用原生POST,所以要设置一下服务器才能正确解释POST过去的数据
  Vue.http.options.emulateJSON = true;
  //定义mainPage页面
  var mainPage = Vue.extend({
   template : "#main-page-temp"
  })
  //定义detailPage页面
  var detailPage = Vue.extend({
   template : "#detail-page-temp",
   components : {
    'album' : Album
   }
  })
  // 根组件
  var showAlbum = Vue.extend({
   components : {
    'main-page' : mainPage,
    'detail-page' : detailPage
   }
  })
  // 实例化路由
  var router = new VueRouter();
  // 配置路由
  router.map({
   '/main-page' : {
    name : 'mainPage',
    component: mainPage
   },
   //这里使用路由的动态片段
   '/detail-page/:inspection_id/:image_type' : {
    name : 'detailPage',
    component : detailPage
   }
  });
  router.redirect({
   // 重定向任意未匹配路径到 /home
   '*': '/main-page'
  });
  // 启动应用
  // 路由器会创建一个实例,并且挂载到选择符匹配的元素上。
  router.start(showAlbum, '#show-album'); 
});

HTML那边就很简单了:

<template id="main-page-temp">
 <group>
  <cell v-for="list in lists"
     title="测试" value="点击"
     is-link
     v-link="{'name':'detailPage',params: { 'inspection_id': list.inspection_id,'image_type' : list.image_type }}">
  </cell>
 </group>
</template>

<template id="detail-page-temp">
  <album v-ref:album :img-srcs="initImgSrcs" ></album>
  <button style="width: 100%;margin-top: 20px"
  点击我触发getAllImgInfo方法
  </button>
</template>

<div id="show-ablum">
 <!-- 路由外链 -->
 <router-view></router-view>
</div>

现在点击主页上的一条记录,就可以跳转到详情页,在详情页后退,就会回到主页了。这样总体结构就完成了。

二.开发微信上传图片组件

具体的代码就不罗列出来了,我们就按照上面的组件功能清单,说说每个功能怎样完成

1.接收父组件传过来的参数进行上传图片组件的初始化
首先,子组件中设置好props

props : {
 //初始化有无照片
 imgSrcs : {
  type : Array,
  default : []
 },
 //是否可编辑 默认true
 canEdit : {
  type : Boolean,
  default : true
 },
 //最大上传数 默认9
 maxNum : {
  type : Number,
  default : 9
 },
 //上传后的回调
 afterUpload : {
  type : Function
 }
}

然后在父组件中使用子组件时把参数传进去即可

<album v-ref:album 
:img-srcs="initImgSrcs" 
:canEdit="true"
:afterUpload="afterUploadFunction"
>
</album>

2.点击最后那个小相机图案调用微信”从手机相册中选图接口”,用户可以在自己手机上选图
在小相机图案的html中绑定chooseImage方法@click=”chooseImage”

<span class="add-img-icon">
  <img src="../Public/Home/source/image/camera.png" @click="chooseImage">
 </span>

然后在methods中添加该方法,通过wx.chooseImage请求微信选择图片接口。使用微信js-sdk前需要配置,所以我们在组件的ready时就进行配置即可。

ready : function() {
   //配置微信JS-SDK
   this.getSignPackage();
  },
methods : {
 chooseImage : function () {
  var _this = this;
  wx.chooseImage({
   count: _this.maxNum - _this.albums.length, // 默认9
   sizeType: ['original', 'compressed'], // 可以指定是原图还是压缩图,默认二者都有
   sourceType: ['album', 'camera'], // 可以指定来源是相册还是相机,默认二者都有
   success: function (res) {
    var _localIds = res.localIds;
    //记录新增照片信息
    for (var i = 0,len = _localIds.length;i < len;i ++) {
     _this.newImagesCache.push(_localIds[i]);
    }
    //按比例生成缩略图
    _this.renderImage(_localIds);
   }
  });
 }
}

3.选完图片后,图片按比例调整尺寸变成如图所示那样的缩略图
这里要使用到图片预处理,即var img = new Image ();通过实例化一个Image实例去获取原图的尺寸,我们才可以根据这个原图尺寸去计算出相应的等比例缩略图。具体是这样:

var img = new Image();
var $albumSingle = "";
//这里的顺序是先new Image(),然后执行img.src,完了之后图片才算装载完成
//这样最后才会调用onload方法
img.onload = function() {
 albumsData = {
  localId : imgSrcs[i],
  albumSingleStyle : {height : imgWrapWidth + "px"},
  //compressImage是压缩图片的方法,将这个图片实例以及图片父元素的宽度传进去来计算。
  imgElementStyle : _this.compressImage(img,imgWrapWidth)
 };
 _this.albums.push(albumsData);
};
img.src = imgSrcs[i];

特别注意的一个地方:由于每张图片的都有自己的尺寸样式,所以我们要在组件的data选项中添加一个albums的数据作为照片的数据集,里面包含每张照片自己的路径与样式,这样循环渲染每张图片时,才会每张图片对应自己的属性。还有就是,因为相同的图片可以重复上传,所以循环时要加上track-by=”$index”

//每张图片自己的属性
albumsData = {
 localId : imgSrcs[i],
 albumSingleStyle : {height : imgWrapWidth + "px"},
 //compressImage是压缩图片的方法,将这个图片实例以及图片父元素的宽度传进去来计算。
 imgElementStyle : _this.compressImage(img,imgWrapWidth)
};
//将每张图片的属性都放到albums数据集里
_this.albums.push(albumsData);

4.点击相应的图片调用微信“预览图片接口”进行图片预览<img @click="previewImage($index)">

在图片中绑定点击事件,传入该图片的索引,去触发一个方法:

previewImage : function (index) {
 var _albums = this.albums;
 var urls = this.getLocalIds(_albums);
 wx.previewImage({
  current: urls[index], // 当前显示图片的http链接
  urls: urls   // 需要预览的图片http链接列表
});

5.点击每张图片右上角的叉叉可以删除图片
这个在叉上绑定点击事件,这个事件去处理删除图片。

<i class="close-icon" @click="deleteImage($index,album)" v-if="canEdit"></i>

deleteImage方法,由于要记录下用户删除了哪些初始化的图片,所以要在删除时判断一下这张图片是不是初始化时就有的:

deleteImage : function (index,album) {
 // 比较要删除的照片是否在初始化照片里
 for (var i = 0,len = this.oldImagesCache.length;i < len;i ++) {
  if (album.localId === _oldImagesCache[i]) {
   this.deleteImagesList.push(_oldImagesCache[index]);
  }
 }
 this.canEdit && this.albums.$remove(album);
}

6.当图片等于最大图片数时,最后那个小相机图案消失 v-if=”albums.length < 9”

7.暴露出两个方法供别的组件调用①上传图片方法(上传到微信服务器并执行上传成功后的回调)uploadImage ②获取所有图片信息方法,包括初始化相册、删除过的、新增的图片信息getAllImgInfo
怎样暴露方法供别的组件调用,这是个大问题。我也不知道怎样做才是最佳实践,因为做法有多种,比如子组件$dispatch,然后父组件在events里接收一下,但这样好像很麻烦,于是我选择了这样做:
在子组件中使用v-rel:xxx添加该组件索引

<album v-ref:album :img-srcs="initImgSrcs" ></album>

然后在父组件里通过this.$refs.xxx.uploadImage()即可调用子组件暴露出来的方法

本文已被整理到了《JavaScript微信开发技巧汇总》,欢迎大家学习阅读。

为大家推荐现在关注度比较高的微信小程序教程一篇:《微信小程序开发教程》小编为大家精心整理的,希望喜欢。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
js的window.showModalDialog及window.open用法实例分析
Jan 29 Javascript
Javascript中的arguments与重载介绍
Mar 15 Javascript
ECharts仪表盘实例代码(附源码下载)
Feb 18 Javascript
深入理解(function(){... })();
Aug 16 Javascript
Angularjs结合Bootstrap制作的一个TODO List
Aug 18 Javascript
PHP+jquery+ajax实现分页
Dec 09 Javascript
微信小程序 连续旋转动画(this.animation.rotate)详解
Apr 07 Javascript
说说node中的可读流和可写流的区别
Jun 01 Javascript
JavaScript设计模式之单例模式简单实例教程
Jul 02 Javascript
vue 的点击事件获取当前点击的元素方法
Sep 15 Javascript
前端面试知识点目录一览
Apr 15 Javascript
JavaScript代码异常监控实现过程详解
Feb 17 Javascript
Javascript将字符串日期格式化为yyyy-mm-dd的方法
Oct 27 #Javascript
vue开发心得和技巧分享
Oct 27 #Javascript
js获取指定字符前/后的字符串简单实例
Oct 27 #Javascript
简单模拟node.js中require的加载机制
Oct 27 #Javascript
浅谈jquery中next与siblings的区别
Oct 27 #Javascript
vue多级多选菜单组件开发
Sep 08 #Javascript
使用Javascript监控前端相关数据的代码
Oct 27 #Javascript
You might like
destoon文章模块调用企业会员资料的方法
2014/08/22 PHP
PHP字符串比较函数strcmp()和strcasecmp()使用总结
2014/11/19 PHP
如何实现php图片等比例缩放
2015/07/28 PHP
PHP等比例压缩图片的实例代码
2018/07/26 PHP
PHP常用的类封装小结【4个工具类】
2019/06/28 PHP
制作高质量的JQuery Plugin 插件的方法
2010/04/20 Javascript
javascript随机将第一个dom中的图片添加到第二个div中示例
2013/10/08 Javascript
浅谈window对象的scrollBy()方法
2015/07/15 Javascript
基于Jquery实现焦点图淡出淡入效果
2015/11/30 Javascript
JavaScript实现简单的拖动效果
2016/07/02 Javascript
对称加密与非对称加密优缺点详解
2017/02/06 Javascript
react实现pure render时bind(this)隐患需注意!
2017/03/09 Javascript
react开发中如何使用require.ensure加载es6风格的组件
2017/05/09 Javascript
详解用node.js实现简单的反向代理
2017/06/26 Javascript
浅谈Vue.nextTick 的实现方法
2017/10/25 Javascript
基于 Vue 实现一个酷炫的 menu插件
2017/11/14 Javascript
nodejs 十六进制字符串型数据与btye型数据相互转换
2018/07/30 NodeJs
JavaScript设计模式之命令模式实例分析
2019/01/16 Javascript
详解使用JWT实现单点登录(完全跨域方案)
2019/08/02 Javascript
详解element-ui级联菜单(城市三级联动菜单)和回显问题
2019/10/02 Javascript
在vue中把含有html标签转为html渲染页面的实例
2019/10/28 Javascript
vue中beforeRouteLeave实现页面回退不刷新的示例代码
2019/11/01 Javascript
[01:06:59]完美世界DOTA2联赛PWL S2 Magma vs FTD 第一场 11.29
2020/12/02 DOTA
Python中自定义函数的教程
2015/04/27 Python
Python使用MONGODB入门实例
2015/05/11 Python
python交互式图形编程实例(三)
2017/11/17 Python
Python实现按特定格式对文件进行读写的方法示例
2017/11/30 Python
详解程序意外中断自动重启shell脚本(以Python为例)
2019/07/26 Python
Python自省及反射原理实例详解
2020/07/06 Python
使用CSS实现阅读进度条
2017/02/27 HTML / CSS
新闻记者个人求职的自我评价
2013/11/28 职场文书
三八节祝酒词
2015/08/11 职场文书
2016庆祝国庆67周年宣传语
2015/11/25 职场文书
学长教您写论文:经验总结
2019/07/09 职场文书
导游词之贵州织金洞
2019/10/12 职场文书
如何用六步教会你使用python爬虫爬取数据
2022/04/06 Python