实战中的面向对象js

236 阅读3分钟

javaScript是不是面向对象语言?

以前在书上看到的比较好的一段描述,分享出来仅供参考,下面的例子是以大家熟知的person类,在这里对这个例子不做过多的阐述。

在传统的面向对象语言(java)中,我们一般会这样描述自己的做法:“我基于Person类创建了一个叫Bob的新对象。”,而在js这种基于原型的面向对象语言中,我们会这样描述:”我将现有的Person对象扩展成一个叫Bob的新对象。”

js压根没有类,该语言都是基于对象,其所依靠的是一套原型系统(prototype实际上也是一种对象)。这句话也与‘万物皆对象’呼应了哈。

结合之前项目中的代码细说一下(结合vue+es6--class)。

  • 需求:一张人员卡片上有语音通话,视频监控,视频点呼(同微信视频)等功能,并且视频监控和视频电呼不能同时发起,语音通话和视频电话不能同时发起。

  • 做法:抽象功能,一个功能创建一个类;再创建一个状态管理的类对所有功能类做一个状态冲突管理。比如,当处于语音通话中时发起视频电呼,提醒用户是否挂掉语音发起视频等操作。

创建功能类

//创建js文件work.js  workManage.js(管理类)
import workManage from './workMange'

let manage = workManage.getInstance /*生成管理类单例*/
export default class work {
    constructor(id,info){
        this.id=id;
        this.name=info.name;
        this.type=info.type;  /*monitor--视频监控;audio--语音通话;video--视频电呼*/
        this.status='normal'; /*calling--通话中;normal--正常状态;callIn--呼入中;waiting--等待中;*/
        //这里可能根据需求添加属性,比如通信号码等
        manage.addWork(this);
    }
    //业务中断的时候需要重置实例属性
    resetInstance(){
        this.status='normal';
    }
    //发起业务,
    callWork(){
        this.status='waiting'
        switch(this.type){
            case "monitor":
                //调用发起视频监控的api
                breack;
            case "audio":
                //调用语音通话的api
                break;
            case "video"
                //调用视频点呼的api
                break;
        }
    }
    //挂断业务
    hangUp(){
        //和发起业务类似
        this.resetInstance();
    }
    //根据业务需求可继续添加需要的公共方法
}

创建状态管理类

export default class WorkManage {
    constructor(){
        /*创建一个map对象,存所有生成的功能类,做一个总的状态冲突管理*/
        this.workMap=new Map();
    }
    //生成管理单例 保证全局只会有一个管理类
    static getInstance(){
        if(!WorkManage.manager){
            WorkManage.manager=new WorkManage();
        }
        return WorkManage.manager;
    }
    //添加业务
    addWork(work){
        //key是为了日志方便分别才这么取得,全凭喜好
        this.workMap.set(work.name+work.type,work);
    };
    //是否有语音业务冲突
    getCallStatus(param){//参数是业务状态,比如传入calling,就是查看当前是否有通话中的业务
        let data=null;
        for(let [,value] of this.workMap){
            if(value.status===param){
                data=value
            }
        }
        //返回null表示没有找到要查询的业务,反之返回查询业务
        return data;
    };
    //当通信卡片关闭的时候删除缓存
    deleteWork(id){
         for(let [key,value] of this.workMap){
         //销毁的组件处于通话中,挂断业务
            if(value.id===id){
                if(value.status==='calling'||value.status==='callIn'){
                   value.huangUp()
                }
                this.workMap.delete(key)
            }
        }
    }
}

main.js 把管理类挂载全局vue上

import workManage from './../workMagage'
import Vue from './vue'
Vue.prototype.$workManage=workManage.getInstance();

组件中使用

mounted(){
    this.audioWork=new work(manInfo);
    this.monitorWork=new work(manInfo);
    this.videoWork=new work(manInfo);
}
//组件销毁时应该把当前活动中的业务中断,并且删除缓存当前组件创建的类
beforeDestroy(){
    this.$workManage.deleteWork(this.id);
}
methods:{
    //发起语音
    audioToOther(){
        if(this.$workManage('calling')){
            layer.msg('已经有一路语音通话')
            reture;
        }
        this.audioWork.callWork();//外部调用,不需要知道关注api和发起功能业务的细节
    }
     //发起视频监控
    monitorToOther(){
        //做一些视频监控的限制条件和冲突,根据具体需求做判断;
        //发起业务的冲突判断其实也可以写在work.js类中发起业务的方法里面
        this.monitorWork.callWork();
    }
}
  • 因为业务问题,代码可能逻辑不是通,但是大致意思差不多达到了,具体的只需要根据需求增添