select+onchange事件详解

本文深入探讨了一个基于观察者模式的网页交互案例,通过改变下拉菜单的选择来动态调整网页元素的外观和内容。详细分析了原有代码的局限性和改进方向,并引入观察者模式解决多区域监控的问题。通过实例展示了如何将逻辑决策与具体操作解耦,提升代码的可维护性和扩展性。最后,提供了实践应用的拓展思考,包括如何在不同场景中灵活运用观察者模式进行复杂事件监听。
摘要由CSDN通过智能技术生成
<!DOCTYPE html>
<html>
<head>
<title>新建网页</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="description" content="" />
<meta name="keywords" content="" />
<script type="text/javascript">
/*
思路:
1:在select上加一个onchange事件
2:当事件发生时,读取选中的值
3:判断
如果 是 男,  改内容区的背景为灰,  改广告区的内容为男性话题
如果 是 女,  改内容区的背景为粉,  改广告区的内容为女性话题
*/
</script>
<style type="text/css">
div {
padding:10px 0;
border: green 1px solid;
margin-top:20px;
}
</style>
</head>
    <body>
        <select name="gender" onchange="cstyle();">
            <option value="m">男士风格</option>
            <option value="f">女士风格</option>
        </select>
        <div id="content">
        这是内容区,背景要随样式变
        </div>
         
        <div id="ad">
         这是广告区,内容要变
        </div>
        <div id="footer"></div>
</body>    
    <script type="text/javascript">
        function cstyle() {
            var sel = document.getElementsByTagName('select')[0];
            var curr = sel.options[sel.options.selectedIndex].value;
 
            if(curr == 'm') {
                document.getElementById('content').style.backgroundColor='gray';
                document.getElementById('ad').innerHTML='足球 新闻 男装';
            } else if(curr == 'f') {
                document.getElementById('content').style.backgroundColor='pink';
                document.getElementById('ad').innerHTML='LV, 减肥 韩剧';
            }
        }
/*
这个效果,通过上面的代码就实现了,  思路非常的中规中矩,面向过程,一步一步来.
 
           分析不足:1:如果突然让你再选择风格时,还要影响到id="footer"的区
           你怎么办?
 
           2:再复杂一点,选择男性风格时,影响footer区,选女性,不影响footer区
 
           思考:当select影响的区域变化时, 我们的cstyle函数,
           尤其是if else段里的内容,要不断修改
 
           从面向对象的角度来看:违反了"开闭原则".
           开闭原则:对扩展是开放的, 对修改是封闭的.
 
           从这个原则出发: 你想多监控footer区,那应该通过增加函数来实现,
但不能修改原函数来实现
 
思考:如何想监控新区域,是通过增加函数,而非修改函数?
想回答这样问题--你仍要思考,为什么我们当前的做法,是修改旧函数? 
 
原因:我们if/else是判断客户的选择
而if/else里面的内容 却是实施对象操作.
 
就是说: 逻辑判决和判断后的操作,耦合的紧密了. 要解耦!
            
用什么思路来做:观察者模式来做
        */
    </script>
</html>

<script type="text/javascript">
/*
还是刚才的同样功能,我们分析了其不足,
用观察者模式来做
 
什么叫观察者模式:
1:一个被观察者,当其发生变化时,把其最新信息传达给观察者
2:一个或多个观者者,发现被观察者变了,做相应的逻辑处理.
 
比如: 页面上有个天气预报, 隔5分钟刷新一下
如果天气变为"雨" ,页面底部显示 请注意带伞.
 
我们设1到多个对象,他们监控天气的变化.
天气变化,引起页面上其他部分的变化.
 
在此例中: 
select是被观察者
2个div是观察者
 
一旦select变化,要把相应的信息投递到div中去,
供div观察.
*/
</script>
<style type="text/css">
div {
padding:10px 0;
border: green 1px solid;
margin-top:20px;
}
</style>
</head>
    <body>
        <select name="gender" onchange="cstyle();">
            <option value="m">男士风格</option>
            <option value="f">女士风格</option>
        </select>
        <div id="content">
        这是内容区,背景要随样式变
        </div>
 
        <div id="ad">
         这是广告区,内容要变
        </div>
        <div id="footer"></div>
        <input type="button" onclick="detachad();" value="别监控广告区了" />
        <input type="button" onclick="atfooter();" value="再多监控footer" />
    </body>
    
    <script type="text/javascript">
        var sel = document.getElementsByTagName('select')[0]; //这是被观察者
 
        var cont = document.getElementById('content');  // 这是2个观察者
        var ad = document.getElementById('ad');
 
        // 被观察者有什么变化,要通知到所有的观察者,供观察者分析并做操作.
 
        // 把所有观察者注册进来
        sel.observers = {};
 
        // 给sel加一个注册方法,把观察他的对象,注册到他的observers"数组"上
        sel.attach = function(key,observer) {
            this.observers[key] = observer;
        }
 
        // 给sel加一个注销观察者的方法,作用与attach相反
        sel.detach = function (key) {
            delete this.observers[key];
        }
 
        // 如果我变化了,还要通知所有观察我的人,通知方法
        sel.onchange = sel.notify = function () {
            for(var k in this.observers) {
                this.observers[k].update(this);
            }
        }
        
        // 疑问: 你怎么知道,通知观察你的那些对象时,他们都有upload方法呢?
        // 在js里没有接口这个概念
        // 事实上,如果是java,php的话,要用观察者模式, 要先实现观察者的接口
        // interface observer{update()}    , interface observee {attach(),detach(),nofity()}
        // 是有接口做强制规范的
        cont.update = function (observee) {
            if(observee.value == 'm') {
                this.style.backgroundColor = 'gray';
            } else if(observee.value == 'f') {
                this.style.backgroundColor = 'pink';
            }
        }
        ad.update = function (observee) {
            if(observee.value == 'm') {
                this.innerHTML = '岛国';
            } else if(observee.value == 'f') {
                this.innerHTML = '减肥';
            }
        }
 
        document.getElementById('footer').update = function () {
            this.innerHTML = '我只是证明我已经观察了'+Math.random();
        }
        /// ====== 服务端写完了  该客户端了=====///
        sel.attach('cont',cont);
        sel.attach('ad',ad);
 
        // 我可以自由的增加或去掉1-2个监控
        function detachad() {
            sel.detach('ad');
        }
        function atfooter() {
            sel.attach('footer',document.getElementById('footer'));
        }
/*
思考:现在的做法,select的变化想多影响一个div或者dom对象
只需要把该dom对象注册成select的观察者
该观察会收到select的变化,并实施自己的update方法.
 
本质:判断逻辑 与 实施影响的逻辑  相分离
分离变化!  把变化单独分离出来,形成自己的逻辑.
 
从面向对象的角度看:
对象与对象之间,应该尽量通信,而不是控制.
*/
 
/*
观察者模式总结:
1:被观察者拥有attach,detach,notify接口
2:观察者拥有update方法
3: 把观察者注册到被观察者上,当被观者变化时, 把自身的变化 update通知到各观察者.
[至于观察者如何变化,那是他的事了,被观者不再操心了,实现了解耦]
本质: 解耦,分离变化
反思: 对象应该尽量通信,减少直接的控制.
*/
/***
作业:
设有如下场景:
用户登陆:
登陆成功了, 判断其邮箱,带不带vip.qq.com(看是不是Q会员,并做不同的处理)
登陆失败了, 记录其失败次数,并记住失败IP,等等.
 
这个过程,如果不用模式来做
 
if($login == true) {
    // 判断邮箱..等等
} else if($login == false) {
    记录失败次数,分析今天失败了几次,要不要出验证码........
}
 
 
// 你这个if /else  做的是不是有点多?
登陆模块,只负责判断登陆 true/false就够了.
 
至于成功失败的后续分析,你写那么多干吗?????
 
用---观察者模式来解决!
 
***/
    </script>
 </html>


转载于:https://my.oschina.net/u/2601503/blog/610379

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值