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

背景

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

相关推荐
爱勇宝1 天前
上线 20 多天后,我才发现小程序的图片上传一直不可用
微信小程序·智能小程序
万亿少女的梦1682 天前
基于微信小程序、Spring Boot与Vue3的智慧养老管理系统设计与实现
spring boot·redis·微信小程序·mybatis·vue3
alxraves3 天前
零代码AI助手:用大模型自动生成微信小程序界面与逻辑
人工智能·微信小程序·notepad++
秃头披风侠_郑3 天前
【uniapp】一文让你学会微信小程序+APP+H5全平台实战指南
前端·微信小程序·uni-app
爱勇宝4 天前
一个家庭成长小程序的 MVP 复盘:看到用户在用我很欣慰
微信小程序·产品·设计
这是个栗子5 天前
uni-app微信小程序开发:高频核心 API(三)
微信小程序·小程序·uni-app
quweiie5 天前
thinkphp8结合jwt与微信小程序接口鉴权
微信小程序·小程序·thinkphp接口·接口鉴权
didiplus7 天前
我在GitHub刷到一个诗词API,顺手写了款小程序
微信小程序
小码哥0687 天前
医院陪诊小程序怎么开发-医院陪诊小程序源码功能-微信小程序 医院健康陪诊陪护系统
微信小程序·小程序·医院陪诊·陪诊系统·陪诊陪诊
书中枫叶8 天前
从「上次几点喂奶」到全栈小程序:我做了个喂宝助手
mongodb·微信小程序·node.js