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

背景

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

相关推荐
andrsted17 小时前
作业发布、课堂检测和错题讲评,用一个小程序完成
学习·微信小程序·小程序·学习方法
汤姆yu18 小时前
基于微信小程序的家电维修预约系统
微信小程序·小程序·家电维修
软件聚导航1 天前
「聚小软 AI 助手」技术升级:从数据库检索到 RAG 知识库问答
前端·数据库·mysql·微信小程序·小程序·ai编程·rag
一叶星殇1 天前
微信小程序 Vant Popup 滚动穿透:页面级与组件级解决方案详解
微信小程序·小程序
2601_963869952 天前
【计算机毕业设计】基于微信小程序的点餐传菜系统设计与实现
微信小程序·小程序·课程设计
北漂燕郊杨哥2 天前
VS Code 安装微信小程序 MCP 介绍
vscode·微信小程序·小程序·mcp
维双云3 天前
2026微信小程序开店用哪个平台?长期稳定运营的系统选择方法
微信小程序·小程序
辛迪聊物业数字化3 天前
【智能楼宇系统有什么用?赋能园区高效 节能 安全】
经验分享·安全·微信小程序·php
Coodor3 天前
使用web也可以写NFC微信小程序拉取
前端·微信小程序·小程序·nfc拉起小程序
太阳之神aboluo4 天前
微信小程序 (1) 基础用法
微信小程序·小程序