我是歌谣 放弃很容易 但是坚持一定很酷 微信公众号关注小歌谣一起学习前后端知识

运行效果

首先我们来看一下原生js实现的效果
在这里插入图片描述
在这里插入图片描述下面就开始直接上代码了

index.html

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    #my-tab {
      width: 500px;
      height: 500px;
      border: 1px solid #000;
      margin: 50px auto;
    }

    .tab-wrapper {
      height: 50px;
      border-bottom: 1px solid #000;
    }

    .tab-item {
      float: left;
      width: 33.33%;
      height: 50px;
      text-align: center;
      line-height: 50px;
    }

    .tab-item.current {
      background-color: #000;
      color: #fff;
    }

    .page-wrapper {
      position: relative;
      height: 450px;
    }

    .page-item {
      display: none;
      position: absolute;
      top: 0;
      left: 0;
      width: 100%;
      height: 450px;
      text-align: center;
      line-height: 450px;
    }

    .page-item.current {
      display: block;
    }
  </style>
</head>
<body>
  
  <div id="my-tab" data='[
    {
      "tab": "选项1",
      "page": "页面1"
    },
    {
      "tab": "选项2",
      "page": "页面2"
    },
    {
      "tab": "选项3",
      "page": "页面3"
    }
  ]'>
    <!-- <div>
      ...tab按钮
    </div>
    <div>
      ...页面
    </div> -->
  </div>
  <script src="js/utils.js"></script>
  <script src="js/tpl.js"></script>
  <script src="js/myTab.js"></script>
  <script>
    new MyTab('#my-tab');
  </script>
</body>
</html>

util.js

var tools = (function () {
  function tplReplace (tpl, replaceObj) {
    return tpl.replace(/\{\{(.*?)\}\}/g, function (node, key) {
      return replaceObj[key.trim()];
    })
  }

  return {
    tplReplace: tplReplace
  }
})();

tpl.js

var tpl = (function () {
  
  function tab (field) {
    switch (field) {
      case 'tab':
        return (
          `<div class="tab-item {{ current }}">{{ tab }}</div>`
        );
      case 'page':
        return (
          `<div class="page-item {{ current }}">{{ page }}</div>`
        );
      default:
        break;
    }
  }

  return {
    tab: tab
  }
})();

Mytab.js

;(function (doc, tpl, tools) {
  function MyTab (el) {
    this.el = doc.querySelector(el);
    this.data = JSON.parse(this.el.getAttribute('data'));
    this._index = 0;
    
    this.init();
  }

  MyTab.prototype.init = function () {
    this._render();
    this._bindEvent();
  }

  MyTab.prototype._render = function () {
    var tabWrapper = doc.createElement('div');
    var pageWrapper = doc.createElement('div');
    var oFrag = doc.createDocumentFragment();

    tabWrapper.className = 'tab-wrapper';
    pageWrapper.className = 'page-wrapper';

    this.data.forEach(function (item, index) {
      tabWrapper.innerHTML += tools.tplReplace(tpl.tab('tab'), {
        tab: item.tab,
        current: !index ? 'current' : ''
      });

      pageWrapper.innerHTML += tools.tplReplace(tpl.tab('page'), {
        page: item.page,
        current: !index ? 'current' : ''
      });
    });

    oFrag.appendChild(tabWrapper);
    oFrag.appendChild(pageWrapper);

    this.el.appendChild(oFrag);
  }

  MyTab.prototype._bindEvent = function () {
    
    var doms = {
      oTabItems: doc.querySelectorAll('.tab-item'),
      oPageItems: doc.querySelectorAll('.page-item')
    }

    this.el.addEventListener('click', this._handleTabClick.bind(this, doms), false);
  }

  MyTab.prototype._handleTabClick = function () {
    var _doms = arguments[0],
        tar = arguments[1].target,
        className = tar.className.trim();
    
    if (className === 'tab-item') {
      _doms.oTabItems[this._index].className = 'tab-item';
      _doms.oPageItems[this._index].className = 'page-item';
      this._index = [].indexOf.call(_doms.oTabItems, tar);
      tar.className += ' current';
      _doms.oPageItems[this._index].className += ' current';
    }
         
  }

  window.MyTab = MyTab;
})(document, tpl, tools);

index.js

// 立即执行函数  
// IIFE   Immediately Invoked Function Expression
//         立即地       调用     (函数      表达式)

// 函数声明 !== 函数表达式
// function test1 () {
//   console.log('Function Declaration');
// }

// // 把一个(匿名)函数(函数声明式)赋值给一个变量的形式  函数表达式
// var test2 = function () {
//   console.log('Function Expression');
// }

// // () 对于函数名后面的括号,叫做执行符号
// test1();
// test2();

// 语法错误,执行符号只能跟在函数表达式后面
// function test () {
//   console.log('Function Declaration');
// }();

// 立即地       调用     (函数      表达式)
// 当一个函数需要立即执行的情况,该函数比较形成表达式形式

// 1
//(1)

//+1
//!1

// ~1

// W3C推荐的立即执行函数的编写规范
// (function () {
//   console.log('Function Expression');
// }());

// 实践中
// ;(function () {
//   console.log('Function Expression');
// })()

// ;(function () {
//   console.log('Function Expression');
// })()

(function test (a, b, c, d) {
  // 1. 可以创建一个与外界没有任何关联的作用域,独立作用域
  // 2. 执行完成以后,自动销毁
  // 3. ES3 ES5 立场上是没有模块概念,立即执行函数来模拟模块化
        // 封闭作用域、抛出接口
  // 向外部抛出一系列属性和方法
  // window上保存属性和方法
  console.log(test);
  console.log(test.length);
  console.log(arguments.length);
  console.log('Hello');
})(1,2,3);

我是歌谣 放弃很容易 但是坚持一定很酷