一个 Vue 地图组件错误引起的思考

最近在 Vue 项目里面编写一个地图组件,发现若是把地图实例挂载到 data 中,会报错。javascript

代码以下:java

export default {
    data () {
        return {
            newMap: null
        }
    },
  	mounted () {
        this.$nextTick(e=>{
      		this.newMap = new maptalks.Map(...)
    	})
    }
}
复制代码

错误信息以下:chrome

经过在控制台中打印 data 中的数据,发现 Vue 给全部的属性都加上 setter/getter ( chrome 控制台会直接打印原始的 object,而重写了 setter/getter 的 object 将会用 "(...)" 代替 )。这个时候恍然大悟,原来 Vue data 中会重写变量的 getter/setter,上面的错误就出如今 Vue 重写地图实例对象的 getter/setter 时。Vue 重写 object 的 setter/getter 是为了跟踪对象,实现响应式。地图实例这样的复杂对象没有必要跟踪,如下是几种能够避免 Vue 的 walk 过程的解决方案。ssh

1、Object.freezeui

地图实例仍然挂到 data 上可是使用 Object.freeze 来告诉 Vue 不要监听this

...
let map = new maptalks.Map(...)
this.newMap = Object.freeze(map)
复制代码

此方法能够避免 Vue 的 walk 错误,可是,咱们保存地图实例到 data 中是为了方便后续调用,若是使用了 Object.freeze ,后面对地图实例操做如:spa

this.newMap.setCursor('crosshair')
复制代码

会报错,错误信息以下:eslint

2、定义成局部变量,放到外面code

let newMap = null
export default {
    data () {
        return {
        }
    },
  	mounted () {
        this.$nextTick(e=>{
      		newMap = new maptalks.Map(...)
    	})
    }
}
复制代码

此方法能够避免 Vue 的 walk 错误,但若是组件有多个实例的话, 会共享同一个 newMap,和以前挂在 data 上的逻辑并不彻底等价。cdn

3、变量名以 _ 开头

export default {
    data () {
        return {
            /* eslint-disable*/
            _newMap: null
            /* eslint-enable */
        }
    },
  	mounted () {
        this.$nextTick(e=>{
      		this._newMap = new maptalks.Map(...)
    	})
    }
}
复制代码

此方法能够避免 Vue 的 walk 错误,同时不影响后面对地图实例进行操做,此方案为本次选用的方案。

4、不预先定义变量,直接挂载到 this 上

export default {
    data () {
        return {
        }
    },
  	mounted () {
        this.$nextTick(e=>{
      		this.newMap = new maptalks.Map(...)
    	})
    }
}
复制代码

此方法也能够避免 Vue 的 walk 错误,同时也不影响后面对地图实例进行操做,但本人喜欢在 Vue 中变量都定义到 data 中,便于管理。

相关文章
相关标签/搜索