preface

This is how I package components according to the business needs of the company

The above is an article about how I encapsulated components according to the business requirements of the company. It is also a small summary of the busy work. Sometimes after a busy development process, we need to stop and think about whether our code is readable. Could you be more robust? At the same time, summarize the business and look back to see if the component code you designed was reasonable based on the business requirements. Could it have been better?

I think those four question marks will always stay with me, because I know that’s the way to grow up.

Small business requirements

Do after the desk management system should know file upload such a function, when it comes to file upload think of their own research on the large file upload case, and summed up such an article. (ps: to achieve multiple large file drag-and-drop upload + large file fragment upload + breakpoint continued + file preview).

The received business requirement is not to upload the file directly to the back end such as above, but to parse the content of the file into the data format that the back end wants, and then send the parsed data to the back end, so as to realize the file upload.

Component packaging

I implemented such a requirement through the elemental-UI upload component and the JS-XLSX library.

Installing a plug-in

npm install element-ui xlsx -S
Copy the code

How to design components

The idea is to collect the file, parse it into JSON data, and then send it to the back end. However, it is worth thinking about how to better design components and maximize their reuse throughout the project.

Here I’m breaking this component down into the template component and the functional component. The group of template components is used to present the UI and collect the files, and the functional components are used to parse the contents of the files into data. Because the upload function of a file from a project may not only parse the file into data, but also directly upload the entire file. If the function of parsing the file contents into JSON data is all in one component, the component will become bloated. It also enables reuse of the template component and maximizes reuse of the functional component.

So how do you wire together the template component and the functional component? At the heart of this is the ability to use Vue’s Mixins to blend in with another component. For details, see Mixins

Custom components

I used the el-Upload component as the template to define the component. Developing this feature required custom uploading methods, so I used the on-change event to collect files and the on-remove attribute to remove files. With the idea of high cohesion and low coupling, I bind these two properties directly to the El-Upload component, instead of passing in the properties when the page uses the custom component and then passing them across classes to the El-Upload. Because the ultimate goal is to get the file data to request the interface, then why not in the data processing itself? So, to make it easier for me to collect the data internally, I pass a callback function externally to perform the following operations after I get the data from the file. The callback function is a mandatory configuration property that represents the subsequent operations after the data from the file is consolidated. (Ps: such as call interface etc…)

Because I’m going to read the file intoJSONData, so the custom component is configured with a propertyheaderStrThis property is an array of objects that hold fields to be passed to the back endkeyAnd which column in the table to read fromstr, and the data type to which the field correspondstype. The question of how to use this configuration item will be discussed later. The diagram below:

The custom component defines a multiple property with a value of true or false to enable multiple file uploads. The component also has self-configured start and end properties to indicate which column the table ends in; One – to – one validation of the file format is also performed inside the component. The component also wraps the callback function internally, wrapping it as a Promise object so that multiple files can be uploaded concurrently.

After a custom component can collect a file into a fileList, you need a functional component to parse the data from the file.

Parse the file into JSON data

The use of Vue was described aboveMixinsSo I mixed in the functional components with the custom componentsUploadXlsxThen the custom component can directly access the methods of the functional component.

In the functional component, two methods are exposed:

  • One way is tohandlerReaderFileUsed to read the contents of the file, through hereFileReaderTo read a file and usexlsxConvert the table object toJSONObject (ps: here is the usexlsxLibrary provides theXLSX.utils.sheet_to_jsonMethods. How to usejs-xlsxSee github for details on this libraryjs-xlsx). This method returns onePromiseObject. If only one XLSX sheet is considered at the beginning of the coding process, but in reality, an XLSX form may have multiple sheets (ps: in the case that a file has multiple sheets), Therefore, unified processing is required (ps: If there are multiple sheets, each sheet is parsed). The parsing is completed by saving each sheet in the array queueJSONValue afterresolveTo the custom template component. Inside this function, passed in by the custom componentstartandendProperty to check the file header, do not give upload if it does not meet the requirements. The specific logic can be viewed source code.

Let’s see.xlsxThe library of the generatedJSONWhat the data looks like:

  • So the other way to do it ishandlerUploadResultTo generate what the real back end wantsJSONThe data. This is where the core configuration item, headerStr, is usedstrProperty is matched against the key of the JSON data generated by the table, and passestypeProperty to generate a realJSONThe data. General idea:

Basically, the functional components are done. Looking back at the custom template component, when processing the collected LIST of files, parse the file into JSON data using the handlerReaderFile method exposed by the function component, and call the callback function. Since the handlerReaderFile method returns an array queue, I use Promise.all inside the custom component for concurrent uploads of files. I pass the return value to the function that wrapped the callback as described above, loop through the arguments, and then call the callback with a resolve wrapper using Promsie. Finally, the value returned by calling the wrapper function is taken as an argument to Promise.all. The specific implementation logic can be viewed source code.

Using the component

  • How to Use:

  • Component presentation:

Coding thinking

  • At the beginning, we only thought about the case of one sheet, but missed the case of multiple sheets. In fact, in the case of only one sheet, the function can be used, but the code of this function component is not robust. What if my colleague writes three sheets for each sheet next time? Then the component misses the data processing. So it’s worth thinking about possibilities and looking at different business possibilities to make your code more robust.

  • I think it is necessary to split the component into the functional component and the template component. Because the file upload implementation scheme can have many possibilities. Now the table data is parsed and then uploaded. How about uploading the file directly next time? The template can then be reused, and the properties don’t conflict with the defined functions, making the component more maintainable. And do after the management system of all probably know bounced the function everywhere, for example, how to better design this kind of demand in the middle of the project, I think you can frame the bomb components (UI) and whether show bounced (functional components) pulled out, so that the whole project of reusable components, this function similar to play box can also go to design a configuration items.

  • Customize configuration items for the component, such as headerStr and callback. The next time a different header is uploaded in the same way, the component can be reused directly. Moreover, components should be as cohesive and low coupled as possible, and what can be handled internally should be handled internally, exposing the results to external users.

The source address

The source address can be viewed as: source code

conclusion

After developing this requirement, I also have a deeper understanding of the basic things such as Promise and object.assign. I still think it’s necessary to encapsulate components and, as time goes on, to have your own component library as much as possible.

Finally, to each big digger friend helpful words hope to reward a star ~ (PS: don’t be stingy oh)