记一次Object.assign对象引用引起的坑,以及采用Proxy的优化

需求

初始需求是 有一个对象,他的某几个属性变更时,触发视图层变动的方法。

当前对象

    _battleState: IBattleState = {
        isGameOver: false,
        bossComing: false,
        overType: OverType.None,
        isRevive: false,
        direction: Direction.S,
        isClearDirectionUnits: false
    }

    get battleState() {
        return this._battleState
    }
    set battleState(val) {
        console.log('this._battleState.direction', this._battleState.direction)
        console.log('set battleState', val)
        console.log('val.direction', val.direction)
        if (val.direction !== this._battleState.direction) {
            console.log('整体 val.direction !== this._battleState.direction', val.direction)
            BattleModelSystem.vmBattleStateJindu(val.direction)
        }
        this._battleState = val
    }

事件触发

console.log('在设置前_BattleModelComp.battleState.direction', _BattleModelComp.battleState.direction)

// 老的错误方法
_BattleModelComp.battleState = Object.assign( _BattleModelComp.battleState, { direction: Direction.W })

// 新的正确方法是在Object.assign前新增一个空对象{}

产生的问题

实际的打印情况是

在设置前_BattleModelComp.battleState.direction S
this._battleState.direction W
BattleModelComp.ts:87 set battleState {isGameOver: false, bossComing: false, overType: 'none', isRevive: false, direction: 'W',}
BattleModelComp.ts:88 val.direction W

在set battleState(val)中的第一行中
this._battleState.direction W
这个值就已经被改为了W

问题所在

是因为对象引用,在

_BattleModelComp.battleState = Object.assign( _BattleModelComp.battleState, { direction: Direction.W })

中Object.assign时,引用对象就已经被改为新的值了

解决问题

在Object.assign中的第一位新增一个空对象,使目标对象是一个新的对象

Object.assign( {},_BattleModelComp.battleState, { direction: Direction.W })

其他方法:使用Proxy

在上面的方法的缺陷
在上面的方法中
get battleState
set battleState
只有在整体被赋值时才会改变
比如:

_BattleModelComp.battleState = Object.assign({}, _BattleModelComp.battleState, { direction: Direction.W })

如果只改变一个属性则不会被触发,如下面的

_BattleModelComp.battleState.direction = Direction.W

这个时候就尝试Proxy的改进

    _battleState: IBattleState = {
        isGameOver: false,
        bossComing: false,
        overType: OverType.None,
        isRevive: false,
        direction: Direction.S,
        isClearDirectionUnits: false
    }
    get battleState() {
        return this.proxy_battleState
    }
    set battleState(val) {
        for (const key in this._battleState) {
            this.proxy_battleState[key] = val[key]
        }
    }
    proxy_battleState: IBattleState = {
        isGameOver: false,
        bossComing: false,
        overType: OverType.None,
        isRevive: false,
        direction: Direction.S,
        isClearDirectionUnits: false
    }
    constructor() {
        super();
        this.proxy_battleState = new Proxy(this._battleState, handler);
    }

const handler = {
    set(obj, prop, value) {
        if (prop == 'direction' && obj[prop] != value) {
            console.log('direction is change', value, obj[prop])
        }
        obj[prop] = value;
        return true
    }
}

这样无论整体被修改还是局部属性被修改都会监听到

        _BattleModelComp.battleState = Object.assign({}, _BattleModelComp.battleState, { direction: Direction.C }) // 会走set battleState 中的方法,接着全部属性进行proxy
        _BattleModelComp.battleState.direction = Direction.W  // 单个属性进行proxy
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值