Native JS Object-Oriented Tab Bar Switching Case

content

1. Realize the effect

2. Functional requirements

3. Abstract Objects

4. Switching function implementation

5. Add function implementation

 6. Delete function implementation


1. Realize the effect

2. Functional requirements

  1. Click the tab bar to switch the effect.
  2. Click the + sign to add tab items and content items.
  3. Click the x number to delete the current tab item and content item
  4. Double-click the tab item text or the content item text to modify the text content inside.

3. Abstract Objects

Abstract Object: Tab Object

  • This object has a toggle function
  • This object has add function
  • The object has delete function
  • The object has modification capabilities

4. Switching function implementation

First of all, you can take a look at the html structure to prevent you from not knowing what you are getting when you get the element and class name:

<h4>
     Js 面向对象 动态添加标签页
</h4>
<div class="tabsbox" id="tab">
      <!-- tab 标签 -->
      <nav class="fisrstnav">
           <ul>
               <li class="liactive"><span>测试1</span><span class="iconfont icon-guanbi"></span></li>
               <li><span>测试2</span><span class="iconfont icon-guanbi"></span></li>
               <li><span>测试3</span><span class="iconfont icon-guanbi"></span></li>
           </ul>
           <div class="tabadd">
               <span>+</span>
           </div>
       </nav>

       <!-- tab 内容 -->
       <div class="tabscon">
           <section class="conactive">测试1</section>
           <section>测试2</section>
           <section>测试3</section>
       </div>
</div>

In this section we want to achieve the effect:

Sample code:

var that;
class tab{
    constructor(id){
        //获取元素
        that = this;
        this.main = document.querySelector(id);
        this.lis = this.main.querySelectorAll('li');
        this.sections = this.main.querySelectorAll('section');
        this.init();//自动调用init
    }
    init(){
        //init初始化操作让相关元素绑定事件
        for(let i = 0;i<this.lis.length;i++){
            this.lis[i].setAttribute('index',i);//设置索引值
            this.lis[i].onclick = this.toggleTab;
        }
    }
    toggleTab() {
        //clearClass函数是类的公共函数,所有只能通过that调用
        that.clearClass();
        this.className = 'liactive';
        that.sections[this.getAttribute('index')].className = 'conactive';
    }
    clearClass() {
        for(var i = 0;i<this.lis.length;i++) {
            this.lis[i].className = '';
            this.sections[i].className = '';
        }
    }
}
var newtab = new tab('.tabsbox');

In contrucotr, we want to get related elements. Here we must pay attention to the problem of this. We must add this, because this points to the instantiated object . After getting the element, call the init function. The init function is used to bind events to the element. For example, when the page is refreshed, the tab bar has a switch to add these functions, so the init function should be placed in the contrucotr. The index value is set so that when the tab bar is clicked, the bottom content area may also change.

Note: when calling clearClass in toggleTab(), it is that, not this. Because this refers to the person who called the function, which refers to li here, because the toggle function is called when li is clicked. But there is no clearClass method in li, so that should be used, that here refers to the instantiated object

5. Add function implementation

1. Click + to add new tabs and content
2. Step 1: Create a new tab li and new content section
3. Step 2: Append the two created elements to the corresponding parent element.
4. Use insertAdjacentHTML() to directly add the string format element to the parent element

Here is a brief introduction to the syntax of insertAdjacentHTML():

position is the position relative to the element and must be one of the following strings:
'beforebegin' Before the element itself.
'afterbegin' is inserted before the first child node inside the element.
'beforeend' is inserted after the last-child inside the element.
'afterend' After the element itself.
text is the string to be parsed into HTML or XML and inserted into the DOM tree.
 

First we get the element in the constructor:

this.add = this.main.querySelector('.tabadd');
this.ul = this.main.querySelector('.fisrstnav ul');
this.fsection = this.main.querySelector('.tabscon');

 Then add the button binding event in the init initialization function:

this.add.onclick = this.addTab;

Finally create the add function addTab():

addTab() {
    that.clearClass();
    var random = Math.random();
    var li = '<li class="liactive"><span>新选项卡</span><span class="iconfont icon-guanbi"></span></li>';
    var section = '<section class="conactive">测试'+ random +'</section>';
    that.ul.insertAdjacentHTML('beforeend',li);
    that.fsection.insertAdjacentHTML('beforeend',section);
}

At the beginning of the add function, call clearClass to clear the original style and make the newly added tab selected. Let's take a look at the effect:


Why can't the newly added tab switch, and the previous li and section do not clear the class, why is this?

Because this is what we added later, when we get the element when the page is loaded, the element added later is not acquired, so there is no binding click event, and there will be these bugs.

 So we should re-acquire all li and section after clicking the plus button, then we create a new update function updateNode(), and put the parts of li and section in contrucotr into it, when we click the add button each time Get all li and section again every time, so the bug is solved

updateNode() {
    this.lis = this.main.querySelectorAll('li');
    this.sections = this.main.querySelectorAll('section');
}

And add this sentence at the beginning of init:

this.updateNode();

Then add this sentence at the end of addTab:

that.init();

This way every time we add a new tab and content, we will re-fetch and bind the newly added event.

Realize the effect:

 6. Delete function implementation

  • Click on the x to delete the current Ii tab and the current section
  • The x number has no index number, but its parent li has an index number, which is exactly the index number we want
  • So the core idea is: Click the x number to delete the Ii and section corresponding to this index number

First of all, we need to get all the close buttons, so should we put the operation of getting elements in the constructor or in the updateNode?

In fact, we must put the step of getting the close button in updateNode, because the li and the close button are one-to-one correspondence, when a new tab is added, the number of close buttons also needs to be updated

Then we put this sentence in updateNode:

this.remove = this.main.querySelectorAll('.icon-guanbi');

And add a click event in the for loop of init, removeTab is the delete method:

this.remove[i].onclick = this.removeTab;

We create a new delete function removeTab():

removeTab(e) {
    e.stopPropagation();//阻止冒泡 防止触发他的父亲li的切换点击事件
    var index = this.parentNode.getAttribute('index');
    that.lis[index].remove();
    that.fsection[index].remove();
    that.init();
}

In the function first we have to prevent the bubbling, because when the x number is clicked, if there is bubbling, it will also trigger the click event of his father li. Then we get the index number of the corresponding li, delete the corresponding li and section through the remove method, and then get the latest li and section again.

Realize the effect:

When we delete this li in the selected state, we should make its previous li in the selected state

We add the following two sentences to the removeTab:

index--;
that.lis[index] && that.lis[index].click();

Because we delete the current li and want the previous li to be in the selected state, we have to decrement the index number by one, which is what the following && statement means. If the current li is the last one, that is, when the index is 0, then index-- is minus one, so that.lis[index] is false and the latter statement will not be executed. The latter sentence is to manually call the click event, so that the previous li is in the selected state.

We also have a last function, that is, when the li that is not in the selected state is deleted, the original selected state li will remain unchanged.

We just need to add this sentence before index--:

if(document.querySelector('.liactive')) return;

If we delete the li that is not in the selected state, it means that there is a .liactive class, then the following code will not be executed if we return directly. If the li in the selected state is deleted, then the .liactive class does not exist and the following code is executed

Realize the effect:

The modification function will not be explained here. Here is the source code link: https://github.com/Vacricticy/JS_Advanced/tree/master/1.%E9%9D%A2%E5%90%91%E5%AF%B9 %E8%B1%A1/07-%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1%E6%A1%88%E4%BE%8B https://github .com/Vacricticy/JS_Advanced/tree/master/1.%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1/07-%E9%9D%A2%E5%90 %91%E5%AF%B9%E8%B1%A1%E6%A1%88%E4%BE%8B

Guess you like

Origin blog.csdn.net/qq_49900295/article/details/123948360