Modo de publicación de suscriptor / modo de observador-vue (antiguo) principio de respuesta

Definir un objeto ordinario: houseObj house object

Defina una lista de mensajes, información de la casa, lista y luego filtrará la publicación de información apropiada de la lista de mensajes. No se necesita una matriz, porque la matriz tratará la clave como un índice y luego buscará el contenido de la matriz, realizará una copia profunda de la matriz, lo que aumenta la carga de rendimiento, y el uso de objetos puede salvar la copia profunda

 escuche, agregue suscriptores (los requisitos para la casa, la clave es la regulación del tipo de habitación, fn es solo una forma de imprimir la información del suscriptor)

disparador, es publicar el mensaje

Finalmente, la clave se utiliza para determinar las necesidades de cada suscriptor y se publica el mensaje correcto.

    let houseObj = {} // 发布者
    houseObj.list = {} // 缓存列表,不用数组会把key当作索引处理,再去取的话,会进行数组的深拷贝,增加性能负担,而使用对象就可以省去深拷贝

    // 增加订阅者
    houseObj.listen = function (key, fn) {
      // 判断有无
      (this.list[key] || (this.list[key] = [])).push(fn)
    }

    // 发布消息
    houseObj.trigger = function () {
      // 取出消息名称,类数组转换数组
      let key = Array.prototype.shift.call(arguments)
      let fns = this.list[key]
      if (!fns || fns.length === 0) {
        return
      }
      for (let i = 0, fn; fn = fns[i++];) {
        fn.apply(this, arguments) // arguments是形参列表,是一个内置对象,可以拿到这个函数的所有形参
      }
    }

    // 需求(订阅的操作),上面是载体,消息放在缓存列表里面
    houseObj.listen('small', function (size) {
      console.log('小红要买' + size + '平米房子')
    })
    houseObj.listen('big', function (size) {
      console.log('小明要买' + size + '平米房子')
    })

    // 正式发布
    houseObj.trigger('small', 100)
    houseObj.trigger('big', 150)

Encapsular (desacoplar) el código anterior

Utilice un evento de objeto para almacenar: lista de mensajes, agregar suscriptores, publicar funciones

Defina un método de inicialización init, pase un objeto y copie transversalmente todo el contenido del evento a los parámetros del objeto pasados, de modo que el objeto recién creado tenga las funciones de lista de mensajes, suscripción y publicación.

Los siguientes requisitos para el objeto de la casa de houseObj y el almacenamiento de mensajes pueden ser correspondencia uno a uno cuando la noticia se publica oficialmente.

    let event = {
      list: {},
      listen: function (key, fn) {
        (this.list[key] || (this.list[key] = [])).push(fn)
      },
      trigger: function () {
        let key = Array.prototype.shift.call(arguments)
        let fns = this.list[key]
        if (!fns || fns.length === 0) {
          return
        }
        for (let i = 0, fn; fn = fns[i++];) {
          fn.apply(this, arguments)
        }
      }
    }



    let init = function (obj) {
      for (let i in event) {
        obj[i] = event[i]
      }
    }


    let houseObj ={}
    init(houseObj)




    // 需求(订阅的操作),上面是载体,消息放在缓存列表里面
    houseObj.listen('small', function (size) {
      console.log('小红要买' + size + '平米房子')
    })
    houseObj.listen('big', function (size) {
      console.log('小明要买' + size + '平米房子')
    })

    // 正式发布
    houseObj.trigger('small', 100)
    houseObj.trigger('big', 150)

De esta forma, el objeto recién creado se puede suscribir y publicar.

 

Agregar método de eliminación

    event.remove = function (key, fn) {
      // fns保存的是某个key值下的所有信息
      let fns = this.list[key]
      // 判断该key值下是否有信息
      if (!fns) {
        return false
      }
      // 判断删除方法中是否传入特定的参数
      // 如果没有,就将该key值下的所有信息清空
      if (!fn) {
        fns && (fns.length = 0)
      }
      // 如果有传入特定的参数,就让其一一对比,找到对应的参数,删除该项信息 
      else {
        for (let i = fns.length - 1; i >= 0; i--) {
          let _fn = fns[i]
          _fn === fn && (fns.splice(i, 1))
        }
      }
    }

    
    // 订阅信息
    houseObj.listen('big', fn1 = function (size) {
      console.log('小明要买'+ size +'平米房子')
    })
    houseObj.listen('big', fn2 = function (size) {
      console.log('小明要买'+ size +'平米房子')
      })
    houseObj.listen('small', fn3 = function (size) {
      console.log('小明要买'+ size +'平米房子')
    })

    // 删除
    // 删除方法中传入的key值是big,后面的特定参数是fn2,所以会执行event.remove中的else中的语句
    houseObj.remove('big',fn2)
    
    // 发布
    // key值为big的fn1参数下的信息不受影响,size=120可以传入订方法阅中,同理small也不受影响
    houseObj.trigger('big',120)
    houseObj.trigger('small',120)

La descripción detallada es visible en los comentarios del código.

Dado que el código anterior está en el proceso de inicialización, es necesario indicar el rol del objeto y crear una lista y varias funciones de método para cada nuevo objeto, pero no todos los objetos lo necesitan, por lo que debemos refinarlo nuevamente y definir métodos según sea necesario.

Desacoplamiento de nuevo, para que el modelo de publicación-suscriptor sea adecuado para diversas situaciones

    // 封装一个全局的对象,抛出几个方法让用户选择
    let Event = (function (){
      let list = {},
        listen,
        trigger,
        remove;

        listen = function (key, fn) {
          (list[key] || (list[key] = [])).push(fn)
        };

      trigger = function () {
        let key = Array.prototype.shift.call(arguments),
          fns = list[key]
 
        if (!fns || fns.length === 0) {
          return
        }
        for (let i = 0, fn; fn = fns[i++];) {
          fn.apply(this, arguments)
        }
      };

      remove = function (key, fn) {
        let fns = list[key]
        if (!fns) {
          return false
        }
        if (!fn) {
          fns && (fns.length = 0)
        } else {
          for (let i = fns.length - 1; i >= 0; i--) {
            let _fn = fns[i]
            _fn === fn && (fns.splice(i, 1))
          }
        }
      };

      return {
        // 可以简写
        listen: listen,
        trigger,
        remove
      }
    })();

Defina un objeto global, que es una función autoejecutable, declare la lista de caché y varios métodos por separado y, finalmente, tírelo. Permita que los usuarios elijan el método de función deseado por sí mismos. Desempeño mejorado.

usar:

    // 使用方式
    // 订阅需求
    Event.listen('big', fn1 = function (size) {
      console.log("小明要买" + size + "平米的房子")
    })
    Event.listen('small', fn2 = function (size) {
      console.log("小明要买" + size + "平米的房子")
    })
    
    // 删除和发布
    Event.remove('big',fn1)  // 删除key为big,特殊参数为fn1的记录
    Event.trigger('big', 100)  // 发布big消息
    Event.trigger('big', 120)  // 发布big消息
    Event.trigger('small', 90)  // 发布small消息

Use Object.defineProperty () en Vue para lograr capacidad de respuesta

Crea un modelo de suscriptor:

//订阅器模型
var Dep = {
  clientList: {},
  listen: function (key, fn) {
    (this.clientList[key] || (this.clientList[key] = [])).push(fn);
  },
  trigger: function () {
    let key = Array.prototype.shift.call(arguments),
      fns = this.clientList[key];
    if (!fns || fns.length === 0) {
      return;
    }
    for (let i = 0, fn; fn = fns[i++];) {
      fn.apply(this, arguments); //发布消息附带的参数
    }
  }
};

Crea un método de secuestro y vincula a los observadores:

// 劫持方法
let dataHijack = function ({
  data,
  tag,
  datakey,
  selector
}) {
  let value = '',
  el = document.querySelector(selector)
  Object.defineProperty(data, datakey, {
    get: function () {
      console.log("我获取到值了")
      return value;
    },
    set: function (newValue) {
      console.log("我改变值了")
      value = newValue
      Dep.trigger(tag, newValue)
    }
  });
  // 绑定观察者
  Dep.listen(tag, function (text) {
    el.innerHTML = text
  })
}

Usar en archivo html:

<body>
  <div id="app">
    订阅视图-1:<span class="box1"></span>
    订阅视图-2:<span class="box2"></span>
  </div>
  <script src="./obs.js"></script>

  <script>
    // 数据
    var dataObj = {};
    // 数据劫持
    dataHijack({
      data: dataObj,
      tag: 'view-1',
      datakey: 'one',
      selector: '.box1'
    });

    dataHijack({
    data: dataObj,
    tag: 'view-2',
    datakey: 'two',
    selector: '.box2'
    });

    dataObj.one = '这是第一个值'
    dataObj.two = "这是第二个值"
  </script>
</body>

Use el método dataHijack para secuestrar los datos primero, obtenga el a través del selector y luego asigne los datos a través de get () o set () de Object.defineProperty ().

Supongo que te gusta

Origin blog.csdn.net/michaelxuzhi___/article/details/106201584
Recomendado
Clasificación