Agile development is a human-centered, iterative, and gradual development method. In Agile development, the construction of software projects is divided into multiple sub-projects. The results of each sub-project are tested and have the characteristics of integration and operation. The first time I saw the definition of agile development, I was fascinated by agile development. In general, agile development allows us to reuse the code we have used again. Because it is re-used, it is relatively safe. Re-debugging is not as painstaking as it is for the first time, saving time and effort. In the process of constantly reusing code, the existing bugs are constantly fixed. Because of the continuous reuse, this template becomes increasingly independent and the applicable situations become wider and wider, at last, we achieved a copper wall and a wall in terms of security. We were able to achieve whatever we wanted in terms of development, and we were able to face it with ease in terms of maintenance.
Agile development is indeed an interest, but how can we practice this profound martial arts? It is impossible for me to teach martial arts based on people in my own situation, because the company decided to start with an excellent open-source framework after thinking about the power of hard work, read a line of code and use it for me. Because it is a single person, the front-end and back-end have to be arranged. Where should we start from? I have had development experience for one or two months. I think the front-end JS is very time-consuming and I always think that I am doing repetitive things, such as sending ajax requests, operation nodes after receiving results (sometimes incompatible, for example, select and table do not support innerHTML in IE, style will not be automatically converted into strings in IE, instead of cssText, once these situations are met, it is really a great blow to the enthusiasm of programmers, because you need to spend time looking for alternative solutions and debugging), as well as node rotation and pop-up layers, form Verification and other cumbersome tasks. So I am determined to start from the front-end JS. To improve the reusability of JS, I chose to learn from Jquery. It took a few months to read more than half of the results. One of my JS modules, "Unlimited deep node operations" (poor literary talent, not a strange name), came out. With it, I became easy to operate nodes, the Code became streamlined, and no additional code was required to be compatible with the browser. In a chat, the function was completed. First, let's talk about what makes the operation node troublesome:
- When compiling ajax programs, dynamic addition, deletion, and modification of page elements are almost inevitable. Using the attribute innerHTML is a common method, but in IE, table, thead, tfoot, tbody, tr, the innerHTML attributes of col, colgroup, html, title, style, and frameset are read-only, that is, we cannot use innerHTML to update these nodes. (The select statement is not mentioned here. In fact, the select statement will not succeed. It is estimated that it is an IE bug ). Example: (The following $ id represents document. getElementById)
Jquery |
// Execute the Code: $ Id ('jkit '). innerHTML ='Jquery'; // No error is reported in IE, but none of the select option nodes are returned. If you use innerHTML for the table, IE will report the unknown runtime error. |
|
In this case, the commonly used compatibility method is to add an outer element. The example is as follows:
Jquery
|
// Execute the Code: $ Id ('jkit '). innerHTML ='Jkit'; // In this way, IE has successfully changed select, but this method has a disadvantage. If you have registered the select event, all these events will be lost. You need to add code to re-register the event. |
|
- Add a node before and after the specified node. This involves node locating, node creation, and node attribute settings. InnerHTML is usually used only to overwrite all nodes of the DOM element. If you only want to change a subnode of the element, or want to add nodes before and after a subnode, it is counterproductive to use innerHTML, after innerHTML is used, all events registered on the subnode will be lost. If you do not use innerHTML, you have to use the native DOM method, but this alternative solution is also difficult. See the following example:
Jquery Jkit Mars |
// Now I want to add an option before jkit and implement it using the native DOM method: Var newNode = document. createElement ('option '),// Create a node Selector = document. getElementById ('jkit3 '), /* Selector. options can also be used, but getElementsByTagName is more common. So how can we use childNodes? It is best not to. For blank nodes, the processing methods for IE and FF are different, In this example, in FF, the select firstChild is a blank text node, Because there are line breaks and white spaces between select and the first option, FF will create nodes for it, while IE will ignore */ Options = document. getElementsByTagName ('option '); NewNode. setAttribute ('value', 'new '); // NewNode. setAttribute ('text', 'newnode'); text does not support this setting // NewNode. text = 'newnode'; ie does not support this method NewNode. innerHTML = 'newnode '; Selector. insertBefore (newNode, options [1]);// Insert before kit
|
|
After the above code is executed, select has one more option:
Jquery NewNode Jkit Mars
Adding a node requires six codes. Now, only one node is added. What should I do for batch operations? In addition, the native DOM method is not very easy to use, the name is long, and the parameter order is hard to remember. When using it, you have to document it (unless you are working on nodes every day and using these methods every day ). Some people say that it is not very troublesome. I can write these six sentences into a method and then complete batch operations by passing parameters. To some extent, it can reduce the workload, but it is not realistic to look far away. There are three reasons: First, each new node has different attributes and different locations, you have to determine the location of the new node outside the method and determine the attributes to add to the node inside the method, and the attribute to be added to the next node, writing the code in the method can only make it easier for you. Second, the code above shows that adding a node requires you to exclude many incompatible implementation methods, in terms of setting attributes, each element has different attributes and has different compatibility schemes. When you write this method for different elements, you must remember the compatibility solutions for each element. But who dares to say that they can remember all the compatible solutions, and that programmers want to make a difference technically, rely on the improvement of thinking logic rather than memory, there is no need to work hard in this aspect; third, a project is implementing functions, and the next project comes back with similar functions, but there are differences in details. According to the above practices, as you can imagine, your code is very low in reusability. To change some details, you have to re-understand the logic you have written and re-refactor the code for your details. In this way, the efficiency is too low, and agile development is not a question.
As you can see, readers may ask, if this is not the case, can developers really copy and paste it? Certainly, it is impossible. The complete code cannot satisfy all the logic of different packages. But the reusability is very high. The key is to find out the commonalities of different logics and make them independent. The reason why I mentioned the above operation node practice is low reusability is that the Operation node is mixed with the specific logic, that is, the code of the specific logic is too closely related to the code of the Operation node, when the next logic encounters node operations, you must review the logic written last time to reuse the code of the previous operation node, and then separate the code of the Operation node for use. The following describes the infinitely hierarchical node operations developed by me, which are logically independent and irrelevant to the logic.
- The preceding example uses select as an example. option is the child node of select. We operate on a two-layer tree structure. What if we go deeper into it and operate on the child node of the element? How to locate the element descendant node? The following is implemented using the native dom method:
|
// Now I want to add an option before the first li and implement it using the native DOM method: NewNode = document. createElement ('lil '), Table = document. getElementById ('jkit4 '), // Obtain the parent node of li: Uls = table. getElementsByTagName ('ul '), /* Although getElementsByTagName is common, if li is nested in the li label and the brother node of the li parent node also has li, getElementsByTagName will get these nodes, if your html structure is really complicated, it is hard for you to locate the li node you are looking for after obtaining the result. In this case, you only need to find childNodes layer by layer, but we mentioned that childNodes does not act in IE and FF, so you need to perform compatibility processing. */ Lis = table. getElementsByTagName ('lil '); NewNode. innerHTML = 'newnode '; // Insert at the specified position Uls [0]. insertBefore (newNode, lis [0]);
|
|
The preceding implementation is similar to the following. If you encounter a complicated html structure, it may be difficult to locate the structure. Some people say that it is not difficult to locate the structure. I can give an id attribute on the li to be searched, in this way, you can locate the complexity step by step, but I would like to ask if you want to perform batch operations? If there are many rows in the table and each row involves such an operation at the beginning, is it true that each li has a given id? Yes, it is not difficult to use loop, but I am against this practice. If there is a good alternative solution, I prefer to keep the HTML clean. In my development project, I try to give as few features as possible to locate the element-free attribute, because I have flexible enough solutions to find nodes. Speaking of clean HTML, let's talk a little bit about it. How can we keep HTML clean? In my development, HTML is not mixed with any logic javascript code (only some variables that receive background data, and these variables are placed at the end of HTML. If there are too many variables, in group form), event Code such as onclick and onblur will not be embedded into html when registering events for elements. You will not see any onclick in HTML when viewing the source code, event code such as onblur. Go back to the topic of this article! Let's talk about how to simplify our work!
Next we will talk about how to write code to simplify our events. Ignore technical events first. If there is such a JS class, there are several methods in it. These methods are sufficient for us to complete the above and more complex events than above. This assumption exists in the class, because there is only a method name and there is no specific implementation, we call it an interface. What we will talk about below is defining interfaces. When we feel that the methods in interfaces can meet our needs, we will implement them again. (This is a good development process, first planning and then taking action)
- Instantiate an object
In development projects, there are many plug-ins that include common B2C and B2B plug-ins, such as rotation, paging, form verification, and form Element settings, batch upload of images, re-packaging of events, batch processing of events, Automatic completion of searches, ajax operations for shopping carts, and classes of common methods. Therefore, there are many classes in Javascript. Each class corresponds to a js variable. As a result, many common js variables exist. If a variable with the same name is accidentally declared elsewhere during development, the class is removed. To avoid this situation, I encapsulate all classes into a class named $ jkit, so that there is only one public variable. The plug-in class becomes local. How can I access it? I also define a $ CL class, which defines some methods used to access the $ jkit class. In this way, even if there are more plug-ins, there are only two public variables $ CL and $ jkit. $ CL is responsible for calling $ jkit. For example, newObj in $ CL is used to instantiate the method of the plug-in object. NewObj has two parameters. The first parameter specifies the plug-in to be instantiated, and the second parameter is used to initialize the parameter when the plug-in is instantiated. parameters are transmitted as arrays.
Option |
Status |
Attribute |
|
All Dismounting |
|
|
|
|
|
/* The following code instantiates an infinite hierarchy node operation plug-in object, which is equivalent to re-constructing a new object tree with a new member method. In the following example, the new object tree references table, and table is also the root of the new tree. Its descendant objects are determined by the second parameter childs. The root reference of the new tree is the entry to operate its descendant objects. Focus on the second parameter. Childs is an array structure. The first element of the array is tr, which indicates that the child node tr of the root node of the dom reconstructs the new object. If the source dom root node root does not contain tr, the object will not be constructed. If tr is embedded with tr, the node will not be constructed for the embedded tr, that is, the object will only be constructed for the child node, the following will not concern the child. The second element is td th. Why are there two? Because the child node under tr can be th or td. If you want to construct a new object for th td at the same time, you must write it in at the same time and separate it with spaces, check order is not limited. The third element is select ul. Why can the two be written together? Because they are at the same level, they are all at the third layer relative to the root node. You can write at the same level. In the following example, the number is unlimited, that is, the infinite level. The hierarchy of the new object tree corresponds to that of the original dom tree. */ Root = document. getElementById ('category '),
Childs = ['tr', 'td th', 'select U', 'Li option'],
Table = $ CL. newObj ('manode', [root, childs]); |
|
- Member method of the new tree,When reading the following API, remember two points. First, all the methods of the root object and the descendant object are for the original DOM object, such as calling del for the new object, the essence is to delete the corresponding original DOM object. Second, each time the call object is added, deleted, modified, the corresponding branch will be re-constructed.
-
Unique root object Method
- Function map (index1, index2, indexN ){}
This method is used to find descendant nodes. table. map (, 0) will find the first object of the second cell in the second row, that is, the object corresponding to select. When map only has one parameter and the parameter is a DOM native object, the method returns the corresponding new object.
- Function index (DOMElement ){}
This method returns the reference corresponding to the native DOMElement object, table. index (document. getElementById ('lior'), returns [,], and the result is in the form of an array.
-
Unique methods of descendant objects
- Function add (index, html ){}
This method is used to add sibling nodes. index is the displacement relative to the location of the object that calls this method. html is the node to be inserted, html can be any html string conforming to W3c standards
Table. map (2). add (-1 ,''), Add a row before the third row (multiple rows can be inserted at the same time)
Table. map (2). add (-2 ,''), Add a row before the first row of the third row
Table. map (0). add (2 ,''), Add a new row before the first row and the next row
Table. map (1). add (0 ,''). If the index is 0, a new row is added before the current row and the current row is deleted.
Table. map (1). add (''), Omitting the first parameter. This is a special usage. You don't need to care which object is used. A new row will be added in the last line.
Table. map (1, 1). add (1 ,'Add Cells'), Add a cell after the second cell in the second row, and then drill into the node, and so on. You only need to use the map Method to Determine the node.
- Function del (index ){}
This method is used to delete sibling nodes. index is the displacement relative to the location of the object that calls this method.
Table. map (1). del (). If index is omitted, it indicates deleting itself. deleting the second row is equivalent to table. map (1). del (0)
Table. map (0). del (2). Delete the second row next to the currently called object. Delete the third row.
Table. map (2). del (-2). Here, the second row before the current call object is deleted, and the first row is deleted.
Table. map (0, 1 ). del ([0,-]). If index is an array, it is used to delete the sibling node of the specified index. In this case, you do not need to care which object is called, if the index is negative, the value-1 indicates the last one. Here, the first, second, and last th are deleted.
Table. map (0, 1 ). del (0,-1). If there are two parameters, it means to delete the sibling node in the specified range. In this case, you do not need to care which object is called. If the index is negative, it indicates that it starts from the end, -1 indicates the last element. Here, the first element to the last element is deleted. The largest parameter can be used as the first parameter. There is no limit on the size sequence.
- Function getParent (){}
Obtain the native DOM object node corresponding to the parent object of the call object. table. map (). getParent (). tagName is tr
- Function getHigher (){}
Obtain the parent object of the call object. table. map (). getHigher. getNode (). tagName is tr
-
Root object and descendant object Methods
- Function getNode (){}
Obtain the native DOM object node corresponding to the call object. table. getNode (). tagName is table, and table. map (). getNode () is th
- Function sizeOf (){}
Obtain the number of sub-objects of the called object. table. sizeOf () is 3, which indicates there are three rows.
- Function pos (){}
Obtain the location of the call object on all its sibling nodes. The value of table. map (1). pos () is 1.
- Function html (html ){}
Obtain the innerHTML of the native dom object corresponding to the called object. If a parameter is input, assign a value to the innerHTML attribute. (do not assign a value to the innerHTML object that is read-only)
- Function attr (html ){}
Obtain the innerHTML of the native dom object corresponding to the call object. If a parameter is passed, assign a value to the corresponding attribute (not implemented yet)
- Function before (index, html ){}
Add a node to the front of the specified sub-object of the call object. index indicates relative displacement.
Table. before (1 ,''), Add a row before the second row
Table. map (1, 2, 0). before (-1 ,'
- Add li nodes
'), Add a li in front of the last li (the index is negative, indicating that from the end,-1 indicates the last one)
Table. before (''). Omitting the first parameter indicates adding a node before the first child object.
- Function append (index, html ){}
Add a node to the end of the specified sub-object of the called object. index indicates relative displacement.
Table. append (1 ,''), Add a row after the second row
Table. map (1, 2, 0). append (-1 ,'
- Add li nodes
'), Add a li after the last li (the index is negative, indicating that from the end,-1 indicates the last one)
Table. append (''). Omitting the first parameter indicates adding a node after the first child object.
- Function replace (index, html ){}
Use html-generated nodes to replace the native DOM node corresponding to the specified sub-object of the calling object. index is relative displacement.
Table. replace (2 ,'Add row') To add a row and replace it with the second row.
Table. replace (-1 ,'Add row'), Add a row, and replace the last row with it (the index is negative, indicating that the last row starts from the end, and-1 indicates the last row)
- Function clean (index ){}
This method is used to delete sibling nodes. index is the displacement relative to the location of the object that calls this method.
Table. clean (). If index is omitted, the first child object is deleted. deleting the first row is equivalent to table. map (1). del (0)
Table. clean (2), which indicates deleting the third row
Table. clean (-2), which indicates deleting the last row.
Table. map (0 ). clean ([0,-]). If index is an array, the sub-object of the specified index is deleted. If index is negative, the value-1 indicates the last one, delete the first, second, and last th
Table. map (0 ). clean (0,-1). If there are two parameters, the sub-objects in the specified range are deleted. If the index is negative, the value-1 indicates the last one, delete the first element to the last element. If the parameter is large, it can be used as the first parameter. The size sequence is not limited.
- If the root node of the new tree is table and its child node is tbody/thead/tfoot, we will not operate these nodes more often, but directly operate tr, so I made a process to allow skipping these nodes. Of course, if you want to operate tbody, you can pass the parameter ['tbody thead tfoot', 'tr', 'td '] in this way; if you only want to retrieve one of them, you can ['tbody', 'tr', 'td ']. If you directly retrieve tr, You Can ['tr', 'td'], in this case, a new object is generated for all tr in tbody/thead/tfoot.
Conclusion: With such a plug-in, node operations are not just a piece of cake. The three major troubles of operating nodes mentioned previously can be solved. This plug-in has nothing to do with any logic. It can be used without secondary processing. It can be expanded when it cannot meet the requirements. Imagine that one day the development process is like a jigsaw puzzle game. After a combination of developed plug-ins, a project will come out. That's a wonderful thing. The possible results are not as good as expected, but we can expect that, in this direction, events become increasingly simple and inevitable. Because the length is too long, the source code will be explained in detail in the next article.