Object.defineProperty() 方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象。
Object.defineProperty()可以为对象的属性添加特性,每一个被添加过的属性,都会拥有属于自己的getter和setter。 正是有了getter和setter,可以实现数据驱动视图,数据实时绑定的效果。
Object.defineproperty可以接收三个参数
Object.defineProperty(obj, prop, descriptor)
obj 要定义属性的对象(目标对象)
prop 要定义或修改的属性的名称
descriptor 目标对象属性的一些特征(是一个对象)
descriptor 下有6个参数
参数1:
value:属性值
参数2:
writable:对象属性值是否可以被修改 true允许 false不允许
参数3:
configurable:对象属性是否可以被删除 true允许 false不允许
参数4:
enumerable:对象属性是否可被枚举
参数5:
get():给一个属性提供getter方法,当访问这个对象的属性值得时候触发该方法
参数6:
set():给一个属性提供setter方法,当设置属性值得时候触发该方法
示例效果图:
示例源代码
<template> <div class="container"> <h3>vue+openlayers: 利用setSource显示隐藏地图</h3> <p>文件来源:https://xiaozhuanlan.com/vue-openlayers</p> <h4> <el-button type="primary" size="mini" @click="yes">显示结果</el-button> </h4> <div id="vue-openlayers"></div> </div>
</template>
<script> import 'ol/ol.css'; import Map from 'ol/Map'; import View from 'ol/View'; import TileLayer from 'ol/layer/Tile'; import OSM from 'ol/source/OSM'; import {transform } from 'ol/proj' export default { name: 'show', data() { return { map: null, source: new OSM(), } }, methods: { yes(){ let test={name:'111'} this.observe(test) test.name = 'newName' console.log(test.name,1, 'ddd') test.name = 'newName2' console.log(test.name, 2,'ddd') }, observe(data){ if (!data || typeof data !== 'object') { return; } // 取出所有属性遍历 Object.keys(data).forEach(key =>{ this.defineProp(data, key, data[key]) }) }, defineProp (data, key, childVal) { this.observe(childVal) //监听子属性 // 精华部分 Object.defineProperty(data, key, { set: (newVal) => { console.log(`哈哈哈监听到啦!原来的值是${childVal}, 变为${newVal}`) childVal = newVal; }, get: () =>{ return childVal }, enumerable: true, // 可枚举 configurable: false, // 不能再define }) }, initMap() { this.map = new Map({ layers: [ new TileLayer({ source:this.source }) ], target: 'vue-openlayers', view: new View({ center: transform([86, -37.0902],"EPSG:4326","EPSG:3857"), projection: "EPSG:3857", zoom: 2, }), }); }, }, mounted() { this.initMap(); }, }
</script> <style scoped> .container { width: 840px; height: 570px; margin: 50px auto; border: 1px solid #42B983; } #vue-openlayers { width: 800px; height: 400px; margin: 0 auto; border: 1px solid #42B983; position: relative; }
</style>