q icon indicating copy to clipboard operation
q copied to clipboard

Using the Proxy - Challenge from your blog

Open SinaKhalili opened this issue 3 years ago • 0 comments

Hello @zserge 👋🏽 I recently stumbled upon and enjoyed reading your blog post on making this tiny version of Vue! It's a great exercise in conciseness.

At the end of your blog post, you mention if anyone would like to try to write a version of the program by using the javascript proxy object they could try and open a PR. After a bit of trying I came up with:

const proxy = q => {
  const deps = {}
  return new Proxy(q, {
    get(target, p) {
      if ($dep) {
        if (!(p in deps))
          deps[p] = []
        deps[p].push($dep)
      }
      return Reflect.get(...arguments)
    },
    set(target, p, value) {
      const success = Reflect.set(...arguments)
      if (!p.startsWith('$') && success) {
        for (const dep of deps[p]){
          dep(value)
        }
      }
      return success
    }
  })

Which works, but unfortunately it returns a new object instead of mutating the given one. I could not figure out how to get around this, if you know how - I love to know. Instead, it's the client's responsibility to wrap the proxy before like:

let model = {name: 'John'};
model = proxy(model)
Q(el, model)
model.name = 'Jane' // this works

Which is lame LOL. I was wondering how Vue3 got around this problem but turns out they don't solve this problem! The new app constructor is just a function called createApp and if you change the data element afterwards, the page is not updated... (ex.)

let model = {data() : { return {name: "john"} } } // you have to use functions for data now
createApp(model).mount('#app');
model.data = () => {return {name:"jane"}} // Doesn't update the dom

So maybe the proxy approach would require a more thorough change. Maybe even a Q3 branch? Lol.

Anyways that's what I wanted to share. Cheers!

SinaKhalili avatar May 13 '21 07:05 SinaKhalili