English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
Since the project is developed with the thinkPHP backend framework, it has always been a multi-page backend routing, and it's a bit difficult to start using the hot webpack (forgive me for being too naive, and promoting vue is only me...), there is no way, want to use vue, only to improve on the original basis. The great advantage of using webpack is that you can write Vue components in single-file format like .vue, so each component is a .vue file, where to use this component, just import it, and it's really convenient to maintain. However, the project has always been using require.js, and now we want to organize Vue components in this form, and also add vue-router and vue-How to deal with resource? This article takes the development of WeChat image upload component as an example to briefly summarize require.js+vue+vue-router+vue-Resource development process.
Organize your components with require.js
We will have a 'components' directory to store our various components. Each component has its own folder named after its own name, for example, in this example, the album component, it contains the html, js, and css of this component. How to load html and css with require.js, everyone can search Baidu and download the relevant plugins. Therefore, in the js of this component, you can load the relevant dependencies in the define, and finally return the component. Other components can also load this component through define, which also achieves the purpose of modular management of components.
Here, I have summarized a template for writing Vue components using require.js. Use WebStorm to add this template, and every time you write a component, just type a few words and the template will be generated automatically. It's really cool! (The variable componentName is used in the template, and you can fill in your component name when the template is generated.)
define(["vue","text!../js/lib/components/$componentName$/index.html","css!../js/lib/components/$componentName$/index.css"],function (Vue,Template) { // This is the code of the module var $componentName$ = Vue.extend({ template : Template, props : [], data : function() { return { } }, // Called after compilation ends and $el is first inserted into the document ready : function() { }, // Called when starting to destroy the instance. At this time, the instance still has functionality. beforeDestroy : function() { }, methods : { }, events : { } }); return $componentName$; });
Overall preview of this example
To demonstrate the complete process, I made this example into a small single-page called show-album, there are only two pages:
1.The main page is called main-page
2.The detail page is called detail-page
The functions in the detail page include:
Receive parameters passed from the parent component to initialize the upload image component
Click on the cross at the top right corner of each image to delete the image
Click on the last small camera icon to call WeChat's "Select Image from Phone Album Interface", where users can select images on their own phones
After selecting the image, the image is resized proportionally to become a thumbnail as shown in the figure
Click on the corresponding image to call WeChat's "Preview Image Interface" for image preview
When the number of images equals the maximum number of images, the last small camera icon disappears
Expose two methods for other components to call: ① upload image method (upload to WeChat server and execute the callback after upload is successful) uploadImage ② get all image information method, including initialized album, deleted, and newly added image information getAllImgInfo
OK, the introduction is over, now let's get started officially!
1. Use vue-The router does routing, building show-album.js
The whole function is called show-album, so we rename this function's js to show-album.js, the structure of this js is as follows:
define(["vue","vueResource","vueRouter","vAlbum"],function (Vue,VueResource,VueRouter,Album) { // Install the resource module Vue.use(VueResource); // Install the routing module Vue.use(VueRouter); // jQuery sets the Content when executing POST requests-Type is application/x-www-form-urlencoded // So that the server can correctly parse, and when using native AJAX requests, if the Content is not explicitly set-Type, then the default is text/plain, // At this point, the server does not know how to parse the data, so it can only parse the request data by obtaining the original data stream. // Since Vue uses native POST, the server needs to be set up to correctly interpret the data sent in POST. Vue.http.options.emulateJSON = true; //Define the mainPage page var mainPage = Vue.extend({ template : "#main-page-temp" }) //Define the detailPage page var detailPage = Vue.extend({ template : "#detail-page-temp", components : { 'album' : Album } }) // Root component var showAlbum = Vue.extend({ components : { 'main-page' : mainPage, 'detail-page' : detailPage } }) // Instantiate the router var router = new VueRouter(); // Configure the route router.map({ /main-page' : { name : 'mainPage', component: mainPage }, //Here we use the dynamic segment of the route /detail-page/:inspection_id/:image_type' : { name : 'detailPage', component : detailPage } }); router.redirect({ // Redirect any unmatched paths to /home *': '/main-page' }); // Start the application // The router will create an instance and mount it to the element that matches the selector. router.start(showAlbum, '#show-album'); });
The HTML part is very simple:
<template id="main-page-temp"> <group> <cell v-for="list in lists" title="[#1#]" value="Click" 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" Click me to trigger the getAllImgInfo method </button> </template> <div id="show-ablum"> <!-- External link route --> <router-view></router-view> </div>
Now, by clicking on a record on the homepage, you can jump to the detail page, and when you go back in the detail page, you will return to the homepage. This completes the overall structure.
2. Develop WeChat upload image component
The specific code is not listed here, but let's talk about how each feature is completed according to the above component feature list
1.Receive parameters passed from the parent component to initialize the image upload component
First, set up props in the child component
props : { //Initialize whether there are photos imgSrcs : { type : Array, default : [] }, //Whether editable, default true canEdit : { type : Boolean, default : true }, //Maximum number of uploads, default9 maxNum : { type : Number, default : 9 }, //Callback after upload afterUpload : { type : Function } }
Then, when using the child component in the parent component, pass the parameters in
<album v-ref:album :img-srcs="initImgSrcs" :canEdit="true" :afterUpload="afterUploadFunction" > </album>
2Click the last small camera pattern to call the WeChat "Select image from phone album" interface, where users can select images on their own phones
Binding the chooseImage method @click="chooseImage" in the HTML of the small camera pattern
<span class="add-img-icon"> <img src="../Public/Home/source/image/camera.png" @click="chooseImage"> </span>
Then add the method in the methods section, using the wx.chooseImage API to request the WeChat image selection interface. Use WeChat js-Since configuration is required before the SDK, we can configure it in the component's ready event.
ready : function() { //Configure WeChat JS-SDK this.getSignPackage(); }, methods : { chooseImage : function () { var _this = this; wx.chooseImage({ count: _this.maxNum - _this.albums.length, // Default9 sizeType: ['original', 'compressed'], // You can specify whether it is the original image or the compressed image, by default both are available sourceType: ['album', 'camera'], // You can specify whether the source is from the album or camera, by default both are available success: function (res) { var _localIds = res.localIds; //Record the information of the newly added photos for (var i = 0, len = _localIds.length; i < len; i ++) { _this.newImagesCache.push(_localIds[i]); } //Generate thumbnails proportionally _this.renderImage(_localIds); } }); } }
3After selecting the image, the image is resized proportionally to become a thumbnail as shown in the figure
Here we need to use image preprocessing, i.e., var img = new Image() to instantiate an Image instance and obtain the original size of the image. This allows us to calculate the corresponding proportional thumbnail based on this original size. Specifically, it is like this:
var img = new Image(); var $albumSingle = ""; //The order here is to first execute new Image(), then img.src, and only after that is the image considered to be fully loaded //This is how the onload method will be called finally img.onload = function() { albumsData = { localId : imgSrcs[i], albumSingleStyle : {height : imgWrapWidth + "px"}, //compressImage is a method to compress images, which takes the image instance and the width of the image parent element to calculate. imgElementStyle : _this.compressImage(img, imgWrapWidth) }; _this.albums.push(albumsData); }; img.src = imgSrcs[i];
A special point to pay attention to: Since each image has its own size and style, we need to add an albums data as a photo dataset in the component's data option, which includes the path and style of each photo. This way, when looping to render each image, each image will correspond to its own properties. Additionally, because the same image can be uploaded multiple times, we need to add 'track' in the loop.-by="$index"
//Properties of each image albumsData = { localId : imgSrcs[i], albumSingleStyle : {height : imgWrapWidth + "px"}, //compressImage is a method to compress images, which takes the image instance and the width of the image parent element to calculate. imgElementStyle : _this.compressImage(img, imgWrapWidth) }; //Put the properties of each image into the albums dataset _this.albums.push(albumsData);
4.Click the corresponding image to call the WeChat "preview image interface" for image preview<img @click="previewImage($index)">
Bind a click event to the image, pass in the index of the image, and trigger a method:
previewImage : function (index) { var _albums = this.albums; var urls = this.getLocalIds(_albums); wx.previewImage({ current: urls[index], // HTTP link of the currently displayed image urls: urls // List of HTTP links of images to be previewed });
5Click the cross on the upper right corner of each image to delete the image
This is bound to a click event on the cross, and this event handles the deletion of the image.
<i class="close-icon" @click="deleteImage($index, album)" v-if="canEdit"></i>
The deleteImage method, as it needs to record which initial images the user has deleted, so it needs to judge whether this image was originally there when deleting:
deleteImage : function (index, album) { // Compare whether the photo to be deleted is in the initial photo set 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); }
6When the number of images equals the maximum number of images, the last small camera icon disappears v-if="albums.length < 9"
7Expose two methods for other components to call: ① upload image method (upload to WeChat server and execute callback after upload is successful) uploadImage ② get all image information method, including initialized album, deleted, and newly added image information getAllImgInfo
How to expose methods for other components to call is a big issue. I don't know what the best practice is, because there are many ways to do it, such as child component $dispatch, and then the parent component receives it in events, but it seems a bit麻烦,so I chose to do it this way:
In the child component, use v-rel:xxx add the index of this component
<album v-ref:album :img-srcs="initImgSrcs" ></album>
Then you can call the method exposed by the child component in the parent component through this.$refs.xxx.uploadImage().
This article has been sorted into 'Summary of JavaScript WeChat Development Techniques', welcome to study and read.
I recommend a tutorial on WeChat Mini Program with high attention at present: 'WeChat Mini Program Development Tutorial'. The editor has carefully compiled it, I hope you like it.
That's all for this article. I hope it will be helpful to your studies, and I also hope that everyone will support the Shouting Tutorial more.
Statement: The content of this article is from the Internet, and the copyright belongs to the original author. The content is contributed and uploaded by Internet users spontaneously. This website does not own the copyright, has not been manually edited, and does not assume any relevant legal liability. If you find any content suspected of copyright infringement, please send an email to: notice#oldtoolbag.com (Please replace # with @ when sending an email for reporting. Provide relevant evidence, and once verified, this site will immediately delete the content suspected of infringement.)