Your location:Tech News>News>Script>150 lines of code with micro-channel listening you implement data applet

Latest News

150 lines of code with micro-channel listening you implement data applet

Author:fsadmin

Views:

  After the applet project, we usually use the data to a storage container to use the global object as individual pages general, it will bind to the target app, every page will be able to freely manipulate the object. In practice, however, since the objects and their properties have not responsive conditions, it is not directly involved in the preparation of the business logic, data storage capacity limited to. If in the VueJS project, we may often use to listen for certain whether the data to change, but lack this ability applet.

  In this article, I will use 150 lines of code, with your hands to create a small program can also use listener (hereinafter referred to as VX):

  // a fast assignment function syntactic sugar, the structure can be created {value: a {b: {val: ''''}}} objects

  vx.set ( ''value.a.d '', {val:'' ''})

  // attributes of a listener, if changed, the corresponding function is performed (can be performed multiple times to watch a plurality of functions)

  vx.watch ( ''value.a.d.val '', newVal => {

  console.log ( `val changed to:`, newVal)

  })

  value.a.d.val = 3 // val adapted as follows: 3

  Use VX listeners, we can more easily manage the status of each page. At the same time, we watch with syntax, you can write the business logic more gracefully.

  Sit tight, ready to start a tricycle - see you comment ~: yum:

  Thinking slightly and patted

  In the global object, we do not have to listen each attribute, so the VX main function is set by the setter to set a specific property / getter, at the same time to add the property to add to subscribe to the callback function watch.

  Implementation dependent objects

  First, we need to build a common dependent objects, dependent objects carry a subscription array for storing a set of callback functions, but it also should include some subscription array operating capability (such as adding a subscription, clear Subscribe) function

  class Dep {

  constructor () {

  this.subs = []

  }

  // callback added to the array

  addSub (fn) {}

  delSub (fn) {}

  // Perform each item in the array function

  notify (newVal, oldVal) {

  this.subs.forEach (func => func (newVal, oldVal))

  }

  }

  Global object in each response type attribute (and each of its sub-properties), and should be a new Dep instance remains one relationship, when we listen change, subscribe to execute a callback function, you only need to find the corresponding the update notification to notify instance execution.

  Property setting response of formula

  defineProperty

  Probably because the contact DefineProperty Proxy earlier than the contact''s sake, the code used for the former responsive implementation, Object.defineProperty method will create a new property directly on an object too fast here again specific configuration defineProperty:

  // @param obj the object on which you want to define attributes in

  Name // @param key you want to define or modify the properties of

  Object.defineProperty (obj, key, {

  // if the property can be enumeration

  enumerable: true,

  // This attribute can be deleted

  configurable: true,

  // Visit the property will perform this method

  get: () => {

  return val

  },

  // This method is executed when the property is modified

  set: newVal => {

  val = newVal

  },

  // value & writeble can not and getter / setter simultaneous

  })

  By defineProperty be upper package, we can easily achieve the set responsive property feature on the global object, in this, we combine Dep just defined objects, a new instance is bound to dep new property setter in:

  set (key, val, options = {}, obj = this.store) {

  const dep = new Dep ()

  Object.defineProperty (obj, key, {

  enumerable: true,

  configurable: true,

  get: () => {

  return val

  },

  set: newVal => {

  if (newVal === val) {

  return

  }

  dep.notify (newVal, val)

  val = newVal

  }

  })

  }

  Whenever the corresponding attribute is assigned, it will perform a callback function dependent on the array.

  But this is not enough, we have to think of ways to get to this dep example, in order to rely on its array of filled function.

  Here provides a very simple idea, it is not recommended practice to do so:

  set (key, val, options = {}, obj = this.store) {

  const dep = new Dep ()

  Object.defineProperty (obj, key, {})

  + Return dep

  }

  const valueDep = set ( ''value'', b, {})

  valueDep.addSub (() => {console.log ( ''value changed!'')})

  Although the code can be used, that is looks strange ~: yum: Our tricycle drove into the fork in the road -

  Add a subscription through watch

  We continue to drink water

  <黑客与画家>A book mentioned such a view, I fully understood:

  If you feel that your code is odd, then it is often wrong

  The above is just a string of codes that run through the levels, we need to add more details and thinking, and sometimes just need a little sit down and look at the code, there will be all kinds of ideas pop out:

  The idea of this kind of thing has a feature that it will lead to more ideas.Have you ever noticed, sit down to write something, the idea is to generate half of the time of writing?

  Hide Dep

  The content should be decoupled and external. First, we create a listener class, all the way to encapsulate our listeners are used to, we want it contains the global object and its operating methods (such as watch, set):

  class VX {

  constructor () {

  this.store = Object.create (null)

  }

  watch (key, fn, obj = this.store) {}

  set (key, val, options = {}, obj = this.store) {}

  }

  const vx = new VX ()

  We can add a callback to the object in a property in the watch, you will not have to rely on an array of direct operating Dep. But, we call in the watch business code, how to obtain the obj.key corresponding to it dep?

  We set up a global depHandler, the obj.key-getter in the initiative will be set to the current obj depHandler.dep instance key, then we watch function, as long as the trigger with any operation obj.The key getter, it can be obtained by dep example depHandler, the code of the form:

  + // start does not hold dep examples

  + Let handleDep = null

  class VX {

  watch (key, fn, obj = this.store) {

  + Console.log (obj.key) // using any of the following trigger obj.The key getter, it will automatically reference obj handleDep.Examples of key dep

  + HandleDep.addSub (fn)

  }

  set (key, val, options = {}, obj = this.store) {

  const dep = new Dep ()

  Object.defineProperty (obj, key, {

  enumerable: true,

  configurable: true,

  get: () => {

  + HandleDep = dep

  return val

  },

  set: newVal => {}

  })

  }

  }

  Initiative to collect rely

  We''ve added logic to add a callback function, in fact, can be directly into the getter, first, Dep class encapsulates a ''proactive'' collect collected dependent, he would subscribe to the global handleFn storage array, so that, in the watch function we just trigger obj.The key getter, you can rely on the active collection:

  let handleFn = null

  class Dep {

  addSub (fn) {}

  delSub (fn) {}

  clear () {}

  collect (fn = handleFn) {

  if (fn && !this.subs.find (x => x === fn)) {

  this.addSub (fn)

  }

  }

  notify (newVal, oldVal) {}

  }

  let handleDep = null

  class VX {

  watch (key, fn, obj = this.store) {

  handleFn = fn

  console.log (obj.key)

  }

  set (key, val, options = {}, obj = this.store) {

  const dep = new Dep ()

  Object.defineProperty (obj, key, {

  enumerable: true,

  configurable: true,

  get: () => {

  handleDep = dep

  handleDep.collect ()

  return val

  },

  set: newVal => {}

  })

  }

  }

  When the value of the processing target key chain

  In the previous watch function, we used to trigger the corresponding attribute getter, if we can do about it is the way to call. Here we can encapsulate a general method for processing an object in the form of a string chain:

  // string by ''a.b ''is divided into a ['' a '','' b ''], and then uses a while loop to be completed object chain

  function walkChains (key, obj) {

  const segments = key.split ( ''.'')

  let deepObj = obj

  while (segments.length) {

  deepObj = deepObj [segments.shift ()]

  }

  }

  class VX {

  watch (key, fn, obj = this.store) {

  handleFn = fn

  walkChains (key, obj)

  }

  }

  In the processing target set method string chain slightly different because if set ( ''a.b ''), it does not find a property in our global object, there should be throwing error.

  Actual processing, it is necessary to infer ''obj.a ''and'' obj.a.and b ''are present. Assuming no ''obj.a '', then we should create a new object and the new object is added to the attribute'' b '', so the code walkChains similar function, just a little one determines:

  set (key, val, obj) {

  const segments = key.split ( ''.'')

  // It should be noted that we only deal with the penultimate property

  while (segments.length> 1) {

  const handleKey = segments.shift ()

  const handleVal = obj [handleKey]

  // exist ''obj.The case of a ''

  if (typeof handleVal === ''object'') {

  obj = handleVal

  // does not exist ''obj.a ''is assigned to a property of a non-responsive subject

  } Else if (!handleVal) {

  obj = (

  key = handleKey,

  obj [handleKey] = {},

  obj [handleKey]

  )

  } Else {

  console.trace ( ''already has val'')

  }

  }

  // The last property to be manually assigned

  key = segments [0]

  }

  Business Scenarios

  Applet refresh the data across the page

  We often encounter in the applet page to jump from A to page B, page B if carried out some operations, hoping to A page automatically refresh data. But because A B page jump to a different page (perhaps redirect, perhaps navigate), treatment methods are not the same.

  Navigate using the jump mode, the page A will not be canceled, we typically go to the reservoir A page instance (i.e. the this object A page) by global object, then calls the appropriate method in the direct page B (e.g. A.refreshList ()) refresh operation.

  After the introduction of VX, we can call the watch onload method to add a subscription lifecycle directly:

  // app.js

  import VX from ''@ / utils / suites / vx''

  const vx = new VX ()

  app.vx = vx

  app.store = vx.store

  app.vx.set ( ''userType'', ''Business'')

  // page a

  onLoad () {

  app.vx.watch ( ''userType'', userType => {

  if (userType === ''Business'') {

  // .

  } Else if (userType === ''Administrators'') {

  // .

  }

  }, {

  immediate: true

  })

  }

  // page b

  switchUserType () {

  app.store.userType = ''Administrators''

  }

  Possible problems encountered

  Function sets to watch the execution method to add immediately

  Sometimes we want to add a function by watch while also immediately execute the function once, this time we need to pass additional parameters to define the watch. The problem is that this is not necessarily a function of the synchronization function.

  Simple process as follows:

  class VX {

  async watch (key, fn, options = {immediately: false}, obj = this.store) {

  handleDep = fn

  walkChains (key, obj)

  options.immediately && await fn (options.defaultParams)

  }

  }

  this binding loss problem

  When I delete extended attributes for VX methods, I added a mechanism to execute a callback function to walkChain function and directly call walkChain delete attributes in this method:

  + Function walkChains (key, obj, fn) {

  const segments = key.split ( ''.'')

  let deepObj = obj

  while (segments.length) {

  deepObj = deepObj [segments.shift ()]

  + Fn && fn ()

  }

  }

  del (key, obj = this.store) {

  walkChains (key, obj, handleDep.clear)

  delete obj [key]

  }

  Because handleDep.clear as a parameter passed into walkChains will lose this binding, so the above is actually part of the code is problematic, but with slight modifications like:

  del (key, obj = this.store) {

  + WalkChains (key, obj, () => handleDep.clear ())

  delete obj [key]

  }

  to sum up

  The more than 150 lines of code with small series to introduce you to achieve data listener micro letter applet, we want to help, if you have any questions please give me a message, Xiao Bian will promptly reply to your.In this I am also very grateful for the support of the home-site scripting!

  If you think this article helpful to you, welcome to reprint, please indicate the source, thank you!

  You may also be interested in the article: micro-channel applet picker assembly on objectArray datatype method of micro-channel applet using map components to achieve Obtain city weather or designated city weather data features micro-channel applet from implementation-defined components and custom components using charles gripping micro channel small program packet phone APP packet (HTTP and HTTPS packets) the MAC system and data between pages delivery problems windows using charles gripping micro letter applets and mobile APP packets (http and https packets ) applet compatible Andrews and IOS data processing and pits micro channel small program data stored with values Detailed WeChat applet achieve a nested template template transfer data ways summarized micro-channel applet ajax implement requests the server data and the template through the data function exemplary micro-channel applet wx.request to achieve interactive features background data analysis

Recommend article

Relate article