Requirements describe

Recent work overtime to complete the needs of an uploaded file, sounds simple thinking is also very simple, but easier said than done practice, was accomplished with a lot of problems, to summarize it now, using the vue to build a upload file page will have what problem, some of these problems can also be used other frameworks might have problems.

Platform: It mainly runs in Android and apple’s wechat Webview.

Let’s start with the main technical points:

  1. Dynamic rendering of parent and child components
  2. Initialize and judge data
  3. The input form hides linkage
  4. You can preview the image after uploading it

Problems encountered:

  1. On the iPhone, the click() event is not valid
  2. In wechat Android WebView, the background attribute of the IMG tag is invalid
  3. Preview uploaded images to ensure aspect ratio
  4. On some Android phones, REM units do not display borders

The design would look something like this:

The finished result looks like this:

  1. After first login, the submit button will not be clicked and will be prompted if two options are not selected
  2. When the image is selected, a thumbnail of the selected image is displayed below
  3. After the loading succeeds, the page will be refreshed
  4. The submitted part will not display a schematic diagram and will be replaced with a prompt image. When all images have been uploaded, the prompt will indicate that all images have been uploaded

It is probably such a step process.

Technical point analysis

The UI mainly used on this page includes: prompt, loading, option bar, etc., are all extracted from WEUI style library. Because they are used in wechat public account, the experience will be consistent. The upload part uses post form upload, and I hide the form form. By simulating the upload button, the input Type = ‘file’ label in the form is triggered synchronously when the upload button is clicked, and the native image selection interface is activated. After selecting the image, Clicking the upload button triggers a POST request to upload the image to the background to complete the function.

Dynamic rendering of parent and child components

It can be seen from the design diagram that the design of uploading pictures is basically the same, so it is best to use a vue component to reuse them. By the way, this page uses three components, one for dialog prompt, one for loading, and one for uploading.

In vue, the parameters passed by the child and parent components need to be declared in the props of the child component. Here is the template in my component. I mainly use the following parameters:


	


Copy the code

Then in the parent component we can import the component, declare it, and pass in the parameters needed by the child component in the tag. Here I use V-for to iterate through an array of Result_data, rendering all the components that need to be uploaded. As follows:

	
		


	Copy the code

This way the parent component can pass the data, you can see the official documentation.

Initialize and judge data

This is the worst part of the mission. Because the background will only tell me the fields of pictures that have been uploaded, I need to create some initial data in the front end to compare with those returned by the background, and then judge which ones have been uploaded and need to be displayed, and those that have not been uploaded need to be uploaded.

Note: You can build data only if the amount of data is not large and the data is fixed. It’s better to do this in the background, because the front end is not supposed to deal with the logic of the data.

The data I initialized looks something like this:

	Init_data: [// 0 {name: 'shopphoto', nameCn: 'shopphoto', bgUrl: {backgroundImage: "url('http://near.m1img.com/op_upload/62/146502860635.jpg')", backgroundSize: '100% 100%' }, imgUrl: '', tip: ', isUpload: false}, // 1 {name: 'goodsphoto', nameCn: 'backgroundImage ', bgUrl: {backgroundImage: "url('http://near.m1img.com/op_upload/62/146502865726.jpg')", backgroundSize: '100% 100%' }, imgUrl: '', tip: '', isUpload: false } ]Copy the code

Then I went through the array returned by the background and the array initialized by myself, and used the name field to make an association for comparison. Because the background only returned the fields of uploaded pictures, I could determine which parts were not uploaded. The logic of judgment is as follows:

	
		compareArr (oldArr, newArr) {
    var _this = this
    var _oldArr = oldArr
    var _newArr = newArr
    for (let i = 0, len1 = _newArr.length; i < len1; i++) {
      for (let j = 0, len2 = _oldArr.length; j < len2; j++) {
        if (_newArr[i].name === _oldArr[j].name) {
          let initData = _this.init_data
          initData[i].bgUrl = {
            backgroundImage: "url('http://near.m1img.com/op_upload/62/146520417256.png')",
            backgroundSize: '100% 100%'
          }
          initData[i].isUpload = true
          _this.$set('init_data', initData)
        }
      }
    }
  }
	Copy the code

I’m going to pass this method two arrays. OldArr is the background array, and newArr is the array I initialized myself. Loop through the comparison of the two arrays and make some changes to the data I initialized myself, mainly indicating the image and whether or not to upload the identity field changes.

The input form hides linkage

Click () when you click on the upload button, call a method, select the corresponding input tag, and trigger a click() event. This is usually done on iphones, which may not support input type= ‘file’ tags. I found some solutions on the Internet, but it didn’t work after trying. Finally, I tried and found a solution, which will be described in the following problems.

The second thing to be careful about is preventing events from bubbling in the form, otherwise you click on the input once and the form will be submitted once.

You can preview the image after uploading it

I can draw on the wisdom of the people…

The idea is to read the image into a Base64 format and then load it into an IMG tag. Realize preview function, here I give a few reference materials, some demo can run directly, change a change can be applied to their own projects.

  1. Mobile front end – Image compression upload practice
  2. Using HTML5’s two apis, front-end JS to complete the image compression
  3. Compatibility issues with mobile thumbnail images uploaded using HTML5 FILE API

After reading their ideas, I can implement this feature, but it does not keep the aspect ratio to fit the screen, I will optimize this part later.

Problems encountered

Let’s solve the four problems one by one:

  1. On the iPhone, the click() event is not valid
  2. In wechat Android WebView, the background attribute of the IMG tag is invalid
  3. Preview uploaded images to ensure aspect ratio
  4. On some Android phones, REM units do not display borders

The click() event is invalid on iPhone

I have a similar problem on the web, address, but I can’t do it on the web, but I found that I can call it explicitly inside the tag with onclick= “document.querySelector(‘ input ‘).click(), So I’m binding this onclick=”document.querySelector(‘input’).click() everywhere I need to implicitly call input, and then I’m binding a method with @click on vue to handle the logical aspect.

The IMG tag is invalid with the background attribute

This may be due to the poor support of wechat WebView in Android, because it can be supported in iPhone and other mobile browsers, but it cannot be displayed in Android wechat WebView. This is a compatibility problem, so I choose to add background in DIV at last.

Preview uploaded images to ensure aspect ratio

This actually not difficult also optimization, because the method above is put pictures of base64 an img tag, so can’t fit the aspect ratio, if put it in the background of div – image attributes, and the background – the size set to contain, Set background-color to the same color as the background of the page to simulate browsing images.

On some Android phones, REM units do not display borders

Since the mobile terminal uses REM as the unit, it uses postCSS to process it (i.e. write PX in CSS, and then process it into REM by the processor). The conversion to REM at 1px May be less than 1px displayed on the screen, so no border will be displayed. The solution is to comment the border to prevent the processor from processing the CSS (/*px*/).

I put this page on Github, but it doesn’t work without VUE. If you need it, you can copy it to your vUE project and try it. Code junk, light spray…

Read smoothly, that night to work overtime to two points, and then by bus to go home, to the place of payment, maintenance can’t found bank payments, and there is no balance in WeChat, is want to do the driver teacher said, have no matter to hurriedly go home when payment can be paid, moved a hurriedly go home a real…