JavaScript - day12

50 阅读2分钟

一、递归

简单来说就是再函数之中再一次调用了函数自己,迟早有一天会停下来
  • 何时:专门用于遍历层级不明确的情况 - DOM树和数据(children只能找到儿子层,找不到孙子层)
  • 如何使用:
function 函数名(root){
    第一层要做什么直接做
    判断有没有下一层,如果有下一层则再次调用此方法,只不过传入的实参是自己的下一层	
}
函数名(实际的根)
  • 算法:深度优先!优先遍历当前节点的子节点,子节点遍历完毕才会跳到兄弟节点
  • 缺陷:不要过多使用,性能相对较差,同时开启大量的函数调用,浪费内存
  • 递归 vs 纯循环
    1. 递归:优点:简单易用
         缺点:性能低
    2. 纯循环:优点:几乎不占用性能
          缺点:难

二、绑定事件:3种方式

  • 在HTML上书写事件属性
<elem on事件名="函数名(实参)"></elem>

缺点

  1. 不符合内容与样式与行为的分离原则
  2. 无法动态绑定,一次只能绑定一个元素
  3. 不支持绑定多个函数对象
  • 在js中使用事件处理函数属性
elem.on事件名=function(){操作}

优点

  1. 符合内容与样式与行为的分离原则
  2. 动态绑定,一次能绑定多个元素
    缺点
  3. 不支持绑定多个函数对象
  • 在js中使用事件API:如果不用考虑老IE,他也不错
    1. 主流:elem.addEventListener("事件名",callback);
    2. 老IE:elem.attachEvent("on事件名",callback);
    3. 兼容
if(elem.addEventListener){
        elem.addEventListener("事件名",callback);
}else{
        elem.attachEvent("on事件名",callback);
}
<script>
    // 主流浏览器
    btn.addEventListener('click',function(){
        console.log(1);
    })
    // 老IE(8-)
    btn.attachEvent('onclick',function(){
        console.log(1);
    })
    // 兼容写法
    if (btn.addEventListener) {
        btn.addEventListener('click',function(){
            console.log(1);
        })
    } else {
        btn.attachEvent('onclick',function(){
            console.log(1);
        })
    }
</script>

优点

  1. 符合内容与样式与行为的分离原则
  2. 动态绑定
  3. 支持绑定多个函数对象
    缺点:有兼容性问题

三、select&option只有他们可以简化创建元素&上树

select.add(new Option("innerHTML","value"));

四、练习

// 递归-DOM 给#ul的孩子设置边框
function getArea(root) {
    for(var i = 0; i < root.length; i++) {
        root[i].style.border = "1px solid #fc1"
        if(root[i].children.length > 0) {
            getArea(root[i].children)
        }
    }
}
getArea(ul.children)
<script>
    // 递归 - 数据
    var json=[{"name":"杨俊杰","children":[{"name":"杨俊"},{"name":"杨杰"}]},
              {"name":"冯小龙"},
              {"name":"胡畔","children":[{"name":"胡田","children":[{"name":"胡半"}]}]},
              {"name":"袍哥","children":[{"name":"钟哥","children":[{"name":"小钟","children":[{"name":"钟种"}]}]}]}
             ];
    // 拿到所有人的姓名
    function getName(root) {
        root.forEach(obj=>{
            console.log(obj.name);
            if(obj.children) {//没有就是undefined
                getName(obj.children)
            }
        })
    }
    getName(json)
</script>
<script>
    // 纯循环 - 设置#ul和所有它孩子的边框
    function getArea(root) {
        // 
        var org = ul
        while(1) {
            root.style.border = "1px solid #fc1"
            if(root.firstElementChild) {
                root = root.firstElementChild
            } else if (root.nextElementSibling) {
                root = root.nextElementSibling
            } else {
                while(!root.parentNode.nextElementSibling&&root!=org.lastElementChild) {
                    root = root.parentNode
                }
                root = root.parentNode.nextElementSibling
                if(root == org.lastElementChild) {
                    root.style.border = "1px solid #fc1"
                    break
                }
            }
        }
    }
    getArea(ul)
</script>
<select name="provs">
        <option>—请选择—</option>
        <option>北京市</option>
        <option>天津市</option>
        <option>河北省</option>
        <option>重庆省</option>
</select>

<select name="cities" class="hide">

</select>

<script>
// 二级联动
        var cities=[//JSON:javascript object notation数据
                [],		/*0号下标没有元素*/
                [{"name":'东城区',"value":101},
                 {"name":'西城区',"value":102},
                 {"name":'海淀区',"value":103},
                 {"name":'朝阳区',"value":104},],
                [{"name":'河东区',"value":201},
                 {"name":'河西区',"value":202},
                 {"name":'南开区',"value":203}],
                [{"name":'石家庄市',"value":301},
                 {"name":'廊坊市',"value":302},
                 {"name":'保定市',"value":303},
                 {"name":'唐山市',"value":304},
                 {"name":'秦皇岛市',"value":305}],
                [{"name":'渝中区',"value":401},
                 {"name":'九龙坡区',"value":402},
                 {"name":'沙坪坝区',"value":403},
                 {"name":'渝北区',"value":404},
                 {"name":'江北区',"value":405}]
        ];
// 拿到两个select
var sels = document.querySelectorAll('select')
// 第一个select选中项改变时候
sels[0].onchange = function(){
    // 拿到当前项的下标
    var i = this.selectedIndex
    // 判断是否为为请选择项  如果是
    if(i > 0){
        // 清除第二个li里面所有的内容
        sels[1].innerHTML = ''
        // 让第二个select显示
        sels[1].className = ''
        // 在数组中对应下标的内容做遍历
        cities[i].forEach(obj=>{
            /* // 创建标签
            var opt = document.createElement('option')
            // 设置属性和内容
            opt.innerHTML = obj.name
            opt.value = obj.value
            // 上树
            sels[1].appendChild(opt) */
                                // 简写以上内容
                                sels[1].add(new Option(obj.name,obj.value))
        })
    } else {
        // 清除第二个li里面所有的内容
        sels[1].innerHTML = ''
        // 让第二个select隐藏
        sels[1].className = 'hide'
    }
}
</script>
<!--根据数据渲染多级联动-->
    <div id="category">

    </div>
    <script type="text/javascript">
            var categories=[
                    {"id":10,"name":'男装',"children":[
                            {"id":101,"name":'正装'},
                            {"id":102,"name":'T恤'},
                            {"id":103,"name":'裤衩'}
                    ]},
                    {"id":20,"name":'女装',"children":[
                            {"id":201,"name":'短裙'},
                            {"id":202,"name":'连衣裙'},
                            {"id":203,"name":'裤子',"children":[
                                    {"id":2031,"name":'长裤'},
                                    {"id":2031,"name":'九分裤'},
                                    {"id":2031,"name":'七分裤'}
                            ]},
                    ]},
                    {"id":30,"name":'童装',"children":[
                            {"id":301,"name":'帽子'},
                            {"id":302,"name":'套装',"children":[
                                    {"id":3021,"name":"0-3岁"},
                                    {"id":3021,"name":"3-6岁","children":[
                                            {"id":2031,"name":'长裤'},
                                            {"id":2031,"name":'九分裤'},
                                            {"id":2031,"name":'七分裤',"children":[
                                                    {"id":101,"name":'正装'},
                                                    {"id":102,"name":'T恤'},
                                                    {"id":103,"name":'裤衩'}
                                            ]}
                                    ]},
                                    {"id":3021,"name":"6-9岁"},
                                    {"id":3021,"name":"9-12岁"}
                            ]},
                            {"id":303,"name":'手套'}
                    ]}
            ];
    // 创建函数
    function getSel(arr) {
        // 创建一个select标签
        var sel = document.createElement('select')
        // 向select里面添加一个请选择option标签
        sel.add(new Option('-请选择-',-1))
        // 遍历数组并且设置option
        arr.forEach(obj=>{sel.add(new Option(obj.name,obj.id))})
        // 当select里面的内容发生改变得到时候
        sel.onchange = function(){
            // 拿到当前下标
            var i = this.selectedIndex
            // 循环判断当前select有没有下一个兄弟 有就删除
            while(sel.nextElementSibling) {
                sel.nextElementSibling.remove()
            }
            // 判断是否为请选择项
            if (i > 0) {
                // 判断是否有children
                if (arr[i-1].children) {
                    // 如果有再次调用函数
                    getSel(arr[i-1].children)
                }
            }
        }
        // 上树
        category.appendChild(sel)
    }
    getSel(categories)
</script>
<script type="text/javascript">
    var json = [
        { "name": "杨俊杰", "children": [{ "name": "杨俊" }, { "name": "杨杰" }] },
        { "name": "冯小龙" },
        { "name": "胡畔", "children": [{ "name": "胡田", "children": [{ "name": "胡半" }] }] },
        { "name": "袍哥", "children": [{ "name": "钟哥", "children": [{ "name": "小钟", "children": [{ "name": "钟种" }] }] }] }
    ];
    // 创建函数
    function getUl(arr,parent) {
        // 创建ul
        var ul = document.createElement('ul')
        // 遍历数组
        arr.forEach(obj=>{
            // 创建li
            var li = document.createElement('li')
            // 设置li的内容
            li.innerHTML = obj.name
            // 上树
            ul.appendChild(li)
            // 判断对象是否有children
            if (obj.children) {
                // 再次调用函数
                getUl(obj.children,li)
            }
        })
        // 上树
        parent.appendChild(ul)
    }
    getUl(json,bd)
</script>
<div id="data1"></div>
<script type="text/javascript">
    var data = [        { "id": 1001, "name": '可口可乐', "price": 2.5, "count": 3000 },        { "id": 1003, "name": '百事可乐', "price": 2.5, "count": 5000 },        { "id": 1011, "name": '非常可乐', "price": 2.3, "count": 1000 },        { "id": 1012, "name": '天府可乐', "price": 2.3, "count": 1000 },        { "id": 1013, "name": '地府可乐', "price": 2.3, "count": 1000 },        { "id": 1014, "name": '阳间可乐', "price": 2.3, "count": 1000 },        { "id": 1015, "name": '阴间可乐', "price": 2.3, "count": 1000 },    ];
            //根据数据生成一个表格
    // 创建一个table
    var table = document.createElement('table')
    // 生成表头
    // 创建数组
    var arr = ['序号','名称','价格','数量','操作']
    // 创建行
    var tr = document.createElement('tr')
    // 遍历数组
    arr.forEach(val=>{
        // 创建列
        var td = document.createElement('td')
        // 设置每一列的内容
        td.innerHTML = val
        // 上树
        tr.appendChild(td)
    })
    // 上树
    table.appendChild(tr)

    // 表体
    // 遍历
    data.forEach(obj=>{
        // 创建行
        var tr = document.createElement('tr')
        // 遍历对象
        for(var i in obj) {
            // 创建列
            var td = document.createElement('td')
            // 设置列的内容
            td.innerHTML = obj[i]
            // 上树
            tr.appendChild(td)
        }

        // 设置操作列
        // 创建列
        var td = document.createElement('td')
        // 设置列的内容
        td.innerHTML = '<button onclick = "del(this)">x</button>'
        // 上树
        tr.appendChild(td)
        // 上树
        table.appendChild(tr)
    })
    // 上树
    data1.appendChild(table)
    // 删除函数
    function del(btn) { 
        var bool = confirm('你确定要删除' + btn.parentNode.parentNode.firstElementChild.nextElementSibling.innerHTML + '吗?')
        if (bool) {
            btn.parentNode.parentNode.remove()
        }
    }
</script>