想在小程序中实现一个计算属性来监控表单的必填属性,失败了

背景

小程序中的表单提交,需要校验表单填写完成按钮才是可点击状态,一般做法是每个表单变化的时候都去看是不是所有都填完成,也就是需要在每个可输入的地方做处理,希望能像vue的计算属性一样,在计算属性里面完成计算,不用在每个字段变化时处理

实现

reactive.js

ini 复制代码
let effectFunc = null
let bucket = new WeakMap()
export const reactive = (target) =>{
  for (let key in target) {
      if(target.hasOwnProperty(key)) {
          const value = target[key]
          if (value && typeof value === 'object') {
              target[key] = reactive(value)
          }
          setReactive(target, key, target[key])
      }
  }
  return target
}
export const setReactive = (target, pop, value) => {
  let reactiveValue = value;
   Object.defineProperty(target, pop, {
       get () {
         console.log('取值')
           track(target, pop)
           return reactiveValue
       },
       set(newValue) {
         console.log('设置值')
           if (newValue !== reactiveValue) {
               reactiveValue = newValue;
               trigger(target, pop);
           }
       }
   })
}
const trigger = (target, key) => {
  const mapBucket = bucket.get(target)
  if (!mapBucket) return
  const set = mapBucket.get(key)
  if (set && set.size > 0) {
      set.forEach(effect => {
          effect()
      })
  }
}
const track = (target, key) => {
 if (!effectFunc) return
  let mapBucket = bucket.get(target)
  if (!mapBucket) {
      bucket.set(target, mapBucket = new Map())
  }
  let set = mapBucket.get(key)
  if (!set) {
      mapBucket.set(key, set = new Set())
  }
  set.add(effectFunc)
}
export const computed = (func) => {
  let value;
  let dirty = true;

  const effect = () => {
      dirty = true;
      effectFunc = effect;
      value = func();
      return value;
  };

  const computedValue = {
      get value() {
          if (dirty) {
              value = effect();
              dirty = false;
          }
          return value;
      },
  };

  effect();
  return computedValue;
}

使用

kotlin 复制代码
import {reactive} from './reactive'
data: {
    test: reactive({
      a: 2
    })
}
onLoad: async function () {
    console.log(this.data.test.a)
    this.data.test.a = 7
    this.setData({
      [`test.a`]: 9
    })
    console.log(this.data.test.a)
		
}

问题

取值的时候能走get,设置值的时候不走set 自己仿写了一个极简Page

kotlin 复制代码
class Page {
    data = {}
    constructor(options) {
          this.data = options.data
           if ('onload' in options && typeof options.onload === 'function') {
               options.onload.call(this)
           }
    }
}
 new Page({
      data: reactive({person: {
              age: 3,
              a:5
          }}),
      onload() {
           console.log('页面加载完成', this.data.person.age)
          this.data.person.age = 6
      }
 })

发现set和get都是可以执行的,那应该就是小程序的内部实现机制的问题,也许可以拦截setData实现,下来研究

其他

  • 为什么不用proxy

    因为Proxy是 ECMAScript 6 标准的一部分,而一些老版本的小程序运行环境对ES6特性支持有限,像我的开发工具就不支持

相关推荐
拖孩18 小时前
流量主门槛从 500 降到 100,我的小程序上线 18 小时够到了线
前端·后端·微信小程序
云-缩影19 小时前
做微信小程序,自建服务器还是用云托管:技术选型对比
服务器·微信小程序·小程序
极限挑战哥2 天前
共享电单车联营平台分账架构实践:二清合规与自动分账零人工方案
java·大数据·人工智能·微信小程序·架构·微信公众平台
云-缩影2 天前
拆解微信小程序后端架构:ECS、RDS、SSL 和 VPC 怎么配合
微信小程序·架构·ssl
拖孩2 天前
AI 帮我写的小程序上线 44 天:36 个人进了收银台,8 个人付钱
前端·后端·微信小程序
sinat_267611912 天前
用 AI 开发微信小程序(八):一个极简收纳工具的开发复盘
微信小程序·小程序
李纲明3 天前
微信小程序真机预览白屏或 request 失败:先核 request 合法域名与 TLS,再查体验版与本地缓存
缓存·微信小程序·小程序·小程序开发·devdiy·真机预览·合法域名
计算机毕设定制辅导-无忧学长4 天前
《基于物品协同过滤的闲置书换购微信小程序设计开发》
java·vue.js·spring boot·微信小程序·uniapp·闲置书换购微信小程序·物品协同过滤算法
ngaiwe4 天前
AA我来算小程序实践:把付款人、承担人和结算状态分开建模
微信小程序