Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

微信小程序,实现 watch 属性,监听数据变化 #687

Open
libin1991 opened this issue Jan 4, 2019 · 0 comments
Open

微信小程序,实现 watch 属性,监听数据变化 #687

libin1991 opened this issue Jan 4, 2019 · 0 comments

Comments

@libin1991
Copy link
Owner

目标

在微信小程序实现 watch 属性,监听 data 中的属性,当被监听属性的值改变时,执行我们指定的方法。​​

思路

Vue 的 computedwatch 可以很方便的检测数据的变化,从而做出相应的改变,所以,模仿 vue 肯定是一个不错的选择。

与 Vue 一样,我们使用 ES5 的Object.defineProperty()方法,劫持对象的 getter/setter,从而实现给对象赋值时(调用 setter),执行 watch 对象中相对应的函数,达到监听效果。

代码

不啰嗦,上代码,真实可用。

function observe(obj, key, watchFun, deep, page) {
  let val = obj[key];

if (val != null && typeof val === "object" && deep) {
Object.keys(val).forEach((item) => {
observe(val, item, watchFun, deep, page);
});
}

Object.defineProperty(obj, key, {
configurable: true,
enumerable: true,
set: function(value) {
watchFun.call(page, value, val);
val = value;

  <span class="hljs-keyword">if</span> (deep) {
    observe(obj, key, watchFun, deep, page);
  }
},
<span class="hljs-attr">get</span>: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">return</span> val;
}

});
}

export function setWatcher(page) {
let data = page.data;
let watch = page.watch;

Object.keys(watch).forEach((item) => {
let targetData = data;
let keys = item.split(".");

<span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> i = <span class="hljs-number">0</span>; i &lt; keys.length - <span class="hljs-number">1</span>; i++) {
  targetData = targetData[keys[i]];
}

<span class="hljs-keyword">let</span> targetKey = keys[keys.length - <span class="hljs-number">1</span>];

<span class="hljs-keyword">let</span> watchFun = watch[item].handler || watch[item];

<span class="hljs-keyword">let</span> deep = watch[item].deep;
observe(targetData, targetKey, watchFun, deep, page);

});
}
复制代码

注意事项:

  • watch 只能监听已存在的属性,数组的 push()pop()等方法并不会触发监听函数。

使用

import * as watch from "./watch.js";

Page({
data: {
name: "二狗子"
},

onLoad() {
watch.setWatcher(this);
},

watch: {
name: function(newVal, oldVal) {
console.log(newVal, oldVal);
}
}
});
复制代码

  • 首先在需要的页面引入
  • 在 Page 的onLoad钩子设置监听器

然后就可以愉快的使用了。

总结

watch 会使代码更简洁,逻辑更清晰,在响应式数据处理上很方便。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant