【JavaScript】五个常用功能/案例:Proxy计数器 | Proxy拦截 | 简易vue2响应式功能 | 购物面板 | 定义接口

151 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第4天,点击查看活动详情

前言

记录JavaScript开发中常用的五个功能案例:Proxy计数器 | Proxy拦截 | 简易vue2响应式功能 | 购物面板 | 定义接口,内容基础,简单易学。正可谓基础不牢,地动山摇!快来查看这些基础案例,查漏补缺,巩固基础吧!!!

一、使用Proxy实现访问计数器

使用Proxy给参数对象添加拦截代理功能,并返回这个代理,要求每当通过代理调用该对象拥有的属性时,"count"值加1,否则减1

let count = 0
const _proxy = object => {
    // 补全代码
    return new Proxy(object,{
        get(target,key){
            if(key in target) {
                count++;
                 return target.key
            }else {
                count--;
            }
           
        }
    })
}

点击深入学习ES6 Proxy对象

二、使用Proxy限制用户访问

给参数对象添加拦截代理功能并返回这个代理。要求如下:

  1. 该函数接收多个参数,首个参数为对象,从第二个参数(包括)往后皆是该对象的属性名
  2. 通过该函数给首个参数对象添加拦截器功能,每当该对象访问到该函数第二个参数(包括)往后的属性时,返回"noright"字符串,表示无权限
const _proxy = (object,...prototypes) => {
    // 补全代码
    return new Proxy(object,{
        get(tar,key){
            // includes方法:判断数组中是否含有某元素 
            if(prototypes.includes(key)) return "noright"
            
            return tar[key]
        }
    })
}

三、监听对象更新视图(简易vue2响应式功能)

要求如下:

  1. 监听对象属性的变化
  2. 当"person"对象的属性发生变化时,页面中与该属性相关的数据同步更新 注意:
  3. 必须使用Object.defineProperty实现且触发set方法时更新视图
  4. 可以使用预设代码"_render"函数

点击查看Object.defineProperty()用法

这是一个简单的解法:

<body>
    <style>
        ul {
            list-style: none;
        }
    </style>
    <ul></ul>

    <script>
        var ul = document.querySelector('ul');
        var person = { sex: '男', age: '25', name: '王大锤', height: 28, weight: 32 };
        const _render = element => {
            var str = `<li>姓名:<span>${person.name}</span></li>
                           <li>性别:<span>${person.sex}</span></li>
                           <li>年龄:<span>${person.age}</span></li>
                           <li>身高:<span>${person.height}</span></li>
                           <li>体重:<span>${person.weight}</span></li>`
            element.innerHTML = str;
        }
        _render(ul);
        // 补全代码
        for (let key in person) {
            let oldVal = person[key]
            Object.defineProperty(person, key, {
                get() {
                    return oldVal;
                },
                set(newVal) {
                    if (oldVal !== newVal) {
                        oldVal = newVal;
                        _render(ul);
                    }

                }
            })
        }

    </script>
</body>

这是一个与vue2原理更相似的解法(使用到observedefineReactive):

<body>
    <style>
        ul {
            list-style: none;
        }
    </style>
    <ul></ul>

    <script>
        var ul = document.querySelector('ul');
        var person = { sex: '男', age: '25', name: '王大锤', height: 28, weight: 32 };
        const _render = element => {
            var str = `<li>姓名:<span>${person.name}</span></li>
                           <li>性别:<span>${person.sex}</span></li>
                           <li>年龄:<span>${person.age}</span></li>
                           <li>身高:<span>${person.height}</span></li>
                           <li>体重:<span>${person.weight}</span></li>`
            element.innerHTML = str;
        }
        _render(ul);
        // 补全代码

        function observe(target) {
            if (typeof target !== "object" || target == null) {
                return
            }
            for (const key in target) {
                defineReactive(target, key, target[key])
            }
        }
        
        function defineReactive(obj, key, value) {
            Object.defineProperty(obj, key, {
                get() {
                    return value;
                },
                set(newVal) {
                    if (value !== newVal) {
                        value = newVal;
                        _render(ul);
                    }

                }
            })
        }
        
        observe(person)
    </script>
</body>

Vue2响应式原理可查看我的系列文章:

  1. vue2数据响应式原理——数据劫持(初始篇)
  2. vue2数据响应式原理——数据劫持(对象篇)
  3. vue2数据响应式原理——数据劫持(数组篇)
  4. vue2数据响应式原理——依赖收集和发布订阅

四、购物面板

补全JavaScript代码,要求如下:

  1. 当点击"-"按钮时,商品数量减1
  2. 当点击"+"按钮时,商品数量加1
  3. 每当点击任意按钮时,购物面板中相关信息必须同步更新 注意:
  4. 必须使用DOM0级标准事件(onclick
<body>
    <table>
        <thead>
            <caption>
                商品
            </caption>
        </thead>
        <tbody>
            <tr>
                <td>炸鸡</td>
                <td>28元</td>
                <td><button id="zjtaiduola">-</button></td>
                <td><span id="zjsl">0</span></td>
                <td><button id="zjtaishaola">+</button></td>
            </tr>
            <tr>
                <td>可乐</td>
                <td>5元</td>
                <td><button id="kltaiduola">-</button></td>
                <td><span id="klsl">0</span></td>
                <td><button id="kltaishaola">+</button></td>
            </tr>
            <tr>
                <td>总价:</td>
                <td><span id="total">0</span></td>
            </tr>
        </tbody>
    </table>

    <script type="text/javascript">
        // 补全代码
        var addzj = document.getElementById('zjtaishaola');
        var reducezj = document.getElementById('zjtaiduola');
        var zj = document.getElementById('zjsl');

        var addkl = document.getElementById('kltaishaola');
        var reducekl = document.getElementById('kltaiduola');
        var kl = document.getElementById('klsl');

        var total = document.getElementById('total');

        addzj.onclick = function () {
            zj.innerText = Number(zj.innerText) + 1
            total.innerText = Number(total.innerText) + 28
        }
        reducezj.onclick = function () {
            if (Number(zj.innerText) > 0) {
                zj.innerText = Number(zj.innerText) - 1
                total.innerText = Number(total.innerText) - 28
            }

        }

        addkl.onclick = function () {
            kl.innerText = Number(kl.innerText) + 1
            total.innerText = Number(total.innerText) + 5
        }
        reducekl.onclick = function () {
            if (Number(kl.innerText) > 0) {
                kl.innerText = Number(kl.innerText) - 1
                total.innerText = Number(total.innerText) - 5
            }

        }
    </script>
</body>

在这里插入图片描述

五、定义接口

补全JavaScript代码,完成函数的接口功能。要求如下:

  1. 函数接收两种类型的参数,分别为"get?"和"update?name=xxx&to=yyy","name"、"to"为参数,"xxx"、"yyy"分别为参数对应的值。
  2. 当参数为"get?"时,返回data数据
  3. 当参数为"update?name=xxx&to=yyy"时,将data中所有"name"为"xxx"的项,更改为"name"值为"yyy"
let data = [
   {name: 'nowcoder1'},
   {name: 'nowcoder2'}
]

const _api = string => {
   // 补全代码
   if(string=="get?"){
       return data;
   }else {
       var params=string.split('?')[1].split('&');
       var oldName=params[0].split('=')[1];
       var newName=params[1].split('=')[1];
       data.forEach((item) => {
           if(item.name==oldName){
               item.name=newName
           }
       })
   }
}

split() 方法使用指定的分隔符字符串将一个String对象分割成子字符串数组,以一个指定的分割字串来决定每个拆分的位置。

结语

以上五个案例都是在牛客上刷题时遇到的,内容基础,偏向实战。

如果本篇文章对你有所帮助,还请客官一件四连!❤️