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

背景

小程序中的表单提交,需要校验表单填写完成按钮才是可点击状态,一般做法是每个表单变化的时候都去看是不是所有都填完成,也就是需要在每个可输入的地方做处理,希望能像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特性支持有限,像我的开发工具就不支持

相关推荐
微笑的曙光12 小时前
第八期 · 情绪闯关挑战盒:一个「无惩罚」成就系统的数据建模
java·微信小程序
andrsted16 小时前
练题簿在线免费刷题:顺序续练、优先新题与题型筛选,让复习一轮轮推进
微信小程序·小程序·刷题
拖孩17 小时前
全程 AI 写的小程序,刚接上会员虚拟支付,上线第二天就有人真金白银买单了|双签名、定价、iOS 的坑我全踩了一遍
前端·后端·微信小程序
醒醒11118 小时前
深入浅出:如何用 Python 实现一个小程序污点分析引擎
微信小程序
andrsted19 小时前
练题簿在线免费刷题:Excel、CSV 批量导题与章节整理,把现成表格变成日常题库
学习·微信小程序·小程序·刷题·在线刷题
计算机毕设定制辅导-无忧学长19 小时前
《基于微信小程序的校园文化活动报名与管理系统》
java·spring boot·微信小程序·uniapp·校园文化活动报名与管理小程序
fengGer的bugs1 天前
新生儿喂养记录微信小程序:本地存储、四套主题,以及一份可改期的疫苗体检日程
微信小程序
5G微创业2 天前
去除抖音视频水印的Python实现
python·微信小程序·去水印
WeiXin_DZbishe2 天前
基于微信小程序的本地闲置物品交易平台-计算机毕设 附源码【课程设计】26825
vue.js·spring boot·python·微信小程序·架构·php·课程设计
小蒜学长2 天前
基于微信小程序的医院医疗废弃物追溯管理系统(代码+数据库+LW)
java·spring boot·后端·微信小程序·医疗废弃物