Как реализовать двустороннюю привязку данных в нативном апплете WeChat

внешний интерфейс Апплет WeChat Vue.js React.js

Официальный сайт:qiu8310.github.io/minapp/

автор:Mora

При разработке нативных апплетов поток данных односторонний и не может быть привязан в двух направлениях, но реализовать функцию двусторонней привязки достаточно просто!

Ниже приведен небольшой каркас программы.minappПринцип двустороннего связывания реализован вminapp, вам просто нужно добавить имя атрибута к компоненту в шаблоне wxml.syncДвусторонняя привязка может быть достигнута. Для того, чтобы объяснить его принцип, процесс может быть немного сложнее, но на самом делеminappFramework разобрался с этими сложными деталями!

первый,Чтобы сделать данные двусторонними, следует избегать слишком большого количества источников данных.. 在数据从上到下自然流动的情况下,如果每个组件中都维护它们自己的数据,而又要保持它们数据值的一致,这虽然可以做到,但实现过程并不会简单。 但是也没必要说为了有一个统一的数据源就使用mobxилиreduxЧтобы управлять данными глобально, это немного похоже на убийство курицы ножом. Поскольку двусторонняя привязка существует только между родительским и дочерним компонентами, а данные передаются от родительского к дочернему, данные в родительском компоненте могут использоваться в качестве источника данных в первую очередь. Каждый раз, когда дочерний компонент обновляет данные, он не обновляет свои собственные внутренние данные, а запускает родительский компонент для обновления своих данных через механизм событий, и после того, как родительский компонент обновляет данные, он естественным образом передает обновленные данные дочернему компоненту. компонент. Это обеспечивает двусторонний поток данных!

data-stream

Не все данные должны быть двусторонним привязкой, не все данные являются внешними, подсагматическими также могут иметь свои внутренние данные. Таким образом, второй вопрос, который относится к тому, что мы говорим:Различать, какие данные требуют двусторонней привязки, какие данные требуют, чтобы подкомпоненты поддерживали себя.

использовалvueВсем следует знать, что для достижения двусторонней привязки в vue в шаблоне необходимо выполнить специальную обработку. Например, родительский компонентparentAttrДвусторонняя привязка к дочерним компонентамchildAttr, вам нужно написать это в шаблоне родительского компонента:

<child childAttr.sync="parentAttr" />

Но у апплета не такой простой синтаксис, и даже такие символы, как «.», не допускаются в имени атрибута языка wxml апплета. Вернемся к нашему вопросу,Подсборки должны знать, для каких свойств требуется двусторонняя привязка, для которых требуется собственное обслуживание свойств., Добавьте поле в шаблон (syncAttrMap) специально для того, чтобы сообщить подкомпонентам, что набора данных, который необходимо связать в обоих направлениях, достаточно. Например, приведенный выше пример можно написать так, как это поддерживает апплет WeChat:

<child childAttr="{{parentAttr}}" syncAttrMap="childAttr=parentAttr" />

<!--
  如果同时存在多个双向绑定和不需要双向绑定的属性时,可以写成下面这样:
  p1, p2 分别双向绑定到子组件的 c1, c2,而 p3 单向绑定到 c3 上
-->

<child c1="{{p1}}" c2="{{p2}}" c3="{{p3}}" syncAttrMap="c1=p1&c2=p2" />

Далее необходимо обработатьПроблема с обновлением данных подкомпонентаТеперь в дочернем компоненте есть две части данных: одна — внутренние данные, а другая — данные родительского компонента. Дочерние компоненты могут читать свойстваsyncAttrMapЧтобы получить, какие данные являются внутренними данными, какие данные являются данными родительского компонента, и может знать соответствующий Каково ключевое имя данных в родительском компоненте. Благодаря нативному компонентному подходуsetData不会管你是内部数据,还是父组件中的数据,只要 你调用它去更新数据,它只会更新内部的数据。所以需要另外实现一个新的方法,来自动判断数据源,如果是内部数据, позвонить напрямуюsetData; Если это данные родительского компонента в двусторонней привязке, вы можете инициировать событие, чтобы уведомить родительский компонент об обновлении соответствующего значения.

Таким образом, согласно приведенному выше описанию, родительский компонент должен иметь функцию прослушивания, а дочерний компонент должен иметь интеллектуальную функцию.setDataфункция. Не препятствовать функции слушателя родительского компонента названныйonSyncAttrUpdate, который устанавливает интеллект дочернего компонентаsetDataфункция с именемsetDataSmart, вы можете иметь следующий код:

// 父组件
Component({
  methods: {
    onSyncAttrUpdate(e) {
      this.setData(e.detail) // 子组件传来的需要更新的数据
    }
  }
})

<!-- 父组件的模板 -->
<child childAttr="{{parentAttr}}" syncAttrMap="childAttr=parentAttr" bind:syncAttrUpdate="onSyncAttrUpdate" />
// 子组件
Component({
  properties: {
    childAttr: String,
    syncAttrMap: String
  },
  methods: {
    // 子组件更新数据时,只要调用此方法即可,而不是 `setData`
    setDataSmart(data) {
      // splitDataBySyncAttrMap 函数的实现过程就不说了,只是将对象拆分,大家应该都能实现
      let {parentData, innerData} = splitDataBySyncAttrMap(data, this.data.syncAttrMap)

      // 内部数据使用 setData 更新
      if (Object.keys(innerData).length) {
        this.setData(innerData) // setData 中还支持 callback 的回调,为了简化代码,这里不讨论
      }

      // 双向绑定的父组件数据触发事件让父组件自己去更新
      if (Object.keys(parentData).length) {
        this.triggerEvent('syncAttrUpdate', parentData)
      }
    }
  }
})

На этом простая функция двусторонней привязки завершена. Однако, поскольку дочерний компонент может также содержать другие компоненты, то есть дочерний компонент также может быть родительским компонентом, а родительский компонент также Может быть подкомпонентом. Итак, вышеonSyncAttrUpdate setDataSmartФункция должна быть реализована в каждом компоненте, поэтому не препятствуйте определить публичный объектBaseComponentДля достижения всех вышеперечисленных функций, таких как:

// BaseComponent
const BaseComponent = {
  properties: {
    syncAttrMap: String
  },
  methods: {
    setDataSmart() {
      // ...
    },
    onSyncAttrUpdate() {
      // ...
    }
  }
}

Далее можно мининить BaseComponent в объект каждого компонента, кроме того, в апплете есть специальный компонент:Page, хотя структуры страницы и компонента различаются, Но его тоже следует рассматривать как компонент, но он должен быть родительским компонентом и не может быть дочерним компонентом других компонентов, поэтому необходимо добавитьonSyncAttrUpdateМетод написан во всех определениях Page. все этоminappОсновной принцип двустороннего связывания.

Подождите, последнее:шаблон wxml, нельзя позволять пользователям писать такие сложные операторы каждый раз, когда они пишут двустороннюю привязку? Конечно, нет,minappВо время компиляции шаблон просто трансформируется:

<child childAttr.sync="parentAttr" />

<!-- 由于属性名 syncAttrMap 是固定的,所以完全可以通过编译手段,将上面的模板转成下面这个模板 -->

<child childAttr="{{parentAttr}}" syncAttrMap="childAttr=parentAttr" />

Спасибо, это конец статьи, прошу обратить вниманиеminapp: новое определение разработки мини-программ WeChat


В 2019 году оригинальная новая книга iKcamp «Практика разработки Koa и Node.js» была продана на JD.com, Tmall, Amazon и Dangdang!