Moon系列之Methods、Computed、双向绑定

2023-10-23 16:18

本文主要是介绍Moon系列之Methods、Computed、双向绑定,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

前言

上一篇文章中了解了整个Moon构造函数的逻辑处理,本篇文章主要是去详细分析Moon是如何处理Methods、computed以及它是如何实现双向绑定的,vue.js是通过ES5的defineProperty来实现的,看看二者有何不同。

具体分析

还是通过简单的实例来分析methods、computed等,具体实例如下:

  <div id="app"><p>{{getMsg}}</p></div><script src="./moon.js"></script><script>new Moon({el: '#app',data: {msg: 'hello world'},// 计算属性computed: {getMsg: {get() {let msg = this.get('msg');或者this.$data.msg直接获取return `js ${msg}`}}},methods: {outMsg() {console.log(this.$data.msg);}}});

首先明确几点:

  • 在Js中应用data中的数据必须是this.$data.变量的形式或者通过Moon的get方法
  • computed的使用必须写成get、set形式

methods

首先分析Methods,看看Moon是如何处理的,相关代码如下:

	var initMethods = function (instance, methods) {var initMethod = function (methodName, method) {// 从此处可以看到2点信息:// 1:methods中定义的方法都会被添加到$data(数据中心)// 2:使用apply改变原先methods中的thisinstance.$data[methodName] = function () {return method.apply(instance, arguments);};};// 遍历methodsfor (var method in methods) {initMethod(method, methods[method]);}};

Moon中methods的调用形式有两种:

  1. 直接调用,this.$data.方法
  2. 使用Moon中提供的方式callMethod的形式:Moon实例.callMethod(方法,参数)

computed

计算属性的处理就不会像methods那么简单了,计算属性涉及到双向绑定以及缓存,具体代码如下:

  var initComputed = function (instance, computed) {var setComputedProperty = function (prop) {// 获取observer对象,观察者var observer = instance.$observer;// 调用observe方法,为每一个计算属性创建一个clear清除缓存的函数observer.observe(prop);// 使用Object.defineProperty将计算属性定义到$data中并监听变化Object.defineProperty(instance.$data, prop, {get: function () {var cache = null;// 查找缓存中是否存在指定名称的computed,存在就取缓存中的计算属性if (observer.cache[prop] === undefined) {// 将observer.target就是当前计算属性名称observer.target = prop;// 调用computed中指定的计算属性,并将结果者赋给cachecache = computed[prop].get.call(instance);observer.target = null;// 保存当前计算结果到oberver.cache对象中observer.cache[prop] = cache;} else {cache = observer.cache[prop];}return cache;},set: noop});var setter = null;// computed中的计算属性中set方法都在observer.setter中if ((setter = computed[prop].set) !== undefined) {observer.setters[prop] = setter;}};// 遍历computedfor (var propName in computed) {setComputedProperty(propName);}};

从上面中可以得到计算属性也是被添加到$data中,计算属性的缓存是通过Observer中的cache属性来处理

双向绑定

Vue是基于数据劫持 + 发布者-订阅者模式实现双向绑定的,你可以使用this.name = name这样的简单形式实现视图更新。
Moon中并没有提供这种形式,它采用的是提供专门的set和get方法主动去触发$data中的数据的响应式变更。
具体看看set、get方法的实现:

  • set
    Moon.prototype.set = function (key, val) {// 获取observer观察者对象var observer = this.$observer;// resolveKeyPath处理获取指定的属性名,更新$data中的值var base = resolveKeyPath(this, this.$data, key, val);var setter = null;// 检查是否是计算属性,是则调用计算属性的set方法if ((setter = observer.setters[base]) !== undefined) {setter.call(this, val);}// 通知,清除包含指定属性的所有计算属性的cache(缓存)observer.notify(base, val);// 异步队列更新DOM视图// 实际上是重新调用Moon实例的build方法并执行updated生命周期函数queueBuild(this);};

queueBuid

	var queueBuild = function (instance) {if (instance.$queued === false && instance.$destroyed === false) {instance.$queued = true;setTimeout(function () {// 实例的build方法,更新DOMinstance.build();// updated生命周期函数callHook(instance, 'updated');instance.$queued = false;}, 0);}};
  • get
	Moon.prototype.get = function (key) {// 获取var observer = this.$observer;var target = null;// observer.target表示计算属性的名称(这里主要是用于计算属性初始化过程中的处理逻辑)if ((target = observer.target) !== null) {// 构建map,map中存储每一个属性所在的所有计算属性Mapif (observer.map[key] === undefined) {// key就是$data中的属性,target就是依赖key的计算属性observer.map[key] = [target];} else if (observer.map[key].indexOf(target) === -1) {observer.map[key].push(target);}}return this.$data[key];};

从上面的实现逻辑中可以知道Moon中双向绑定实际的处理如下:

  • 主动调用set方法,实现$data或计算属性的值变化
  • get方法获取 d a t a 中数据,而在该方法中核心点是建立计算属性中的 data中数据,而在该方法中核心点是建立计算属性中的 data中数据,而在该方法中核心点是建立计算属性中的data依赖

只要你在computed中调用 d a t a 中变量,就会在 g e t 中建立 data中变量,就会在get中建立 data中变量,就会在get中建立data与computed之间的Map联系,这就是Moon是如何收集computed的方式。

总结
  • Moon中对于Methods以及Computed的处理,都添加到data数据中心
  • Moon中计算属性采用了Object.defineProperty,普通data中的变量没有采用
  • d a t a 中变量通过 M o o n 实例提供的 s e t 来实现数据响应的,使用 g e t 来获取 data中变量通过Moon实例提供的set来实现数据响应的,使用get来获取 data中变量通过Moon实例提供的set来实现数据响应的,使用get来获取data中的数据。
  • 计算属性中通过get来建立$data中变量与其的联系,使用Observer观察者对象的map来保存
  • 通过set更新 d a t a 中数据之后会重新渲染,再次渲染时拿到的就是更新后的 data中数据之后会重新渲染,再次渲染时拿到的就是更新后的 data中数据之后会重新渲染,再次渲染时拿到的就是更新后的data,即双向绑定

这篇关于Moon系列之Methods、Computed、双向绑定的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/268987

相关文章

VUE动态绑定class类的三种常用方式及适用场景详解

《VUE动态绑定class类的三种常用方式及适用场景详解》文章介绍了在实际开发中动态绑定class的三种常见情况及其解决方案,包括根据不同的返回值渲染不同的class样式、给模块添加基础样式以及根据设... 目录前言1.动态选择class样式(对象添加:情景一)2.动态添加一个class样式(字符串添加:情

Spring Security 从入门到进阶系列教程

Spring Security 入门系列 《保护 Web 应用的安全》 《Spring-Security-入门(一):登录与退出》 《Spring-Security-入门(二):基于数据库验证》 《Spring-Security-入门(三):密码加密》 《Spring-Security-入门(四):自定义-Filter》 《Spring-Security-入门(五):在 Sprin

csu1329(双向链表)

题意:给n个盒子,编号为1到n,四个操作:1、将x盒子移到y的左边;2、将x盒子移到y的右边;3、交换x和y盒子的位置;4、将所有的盒子反过来放。 思路分析:用双向链表解决。每个操作的时间复杂度为O(1),用数组来模拟链表,下面的代码是参考刘老师的标程写的。 代码如下: #include<iostream>#include<algorithm>#include<stdio.h>#

科研绘图系列:R语言扩展物种堆积图(Extended Stacked Barplot)

介绍 R语言的扩展物种堆积图是一种数据可视化工具,它不仅展示了物种的堆积结果,还整合了不同样本分组之间的差异性分析结果。这种图形表示方法能够直观地比较不同物种在各个分组中的显著性差异,为研究者提供了一种有效的数据解读方式。 加载R包 knitr::opts_chunk$set(warning = F, message = F)library(tidyverse)library(phyl

【生成模型系列(初级)】嵌入(Embedding)方程——自然语言处理的数学灵魂【通俗理解】

【通俗理解】嵌入(Embedding)方程——自然语言处理的数学灵魂 关键词提炼 #嵌入方程 #自然语言处理 #词向量 #机器学习 #神经网络 #向量空间模型 #Siri #Google翻译 #AlexNet 第一节:嵌入方程的类比与核心概念【尽可能通俗】 嵌入方程可以被看作是自然语言处理中的“翻译机”,它将文本中的单词或短语转换成计算机能够理解的数学形式,即向量。 正如翻译机将一种语言

flume系列之:查看flume系统日志、查看统计flume日志类型、查看flume日志

遍历指定目录下多个文件查找指定内容 服务器系统日志会记录flume相关日志 cat /var/log/messages |grep -i oom 查找系统日志中关于flume的指定日志 import osdef search_string_in_files(directory, search_string):count = 0

SpringMVC入参绑定特别注意

1.直接在controller中定义一个变量,但是此种传输方式有一个限制就是参数名和请求中的参数名必须保持一致,否则失效。 @RequestMapping("test2")@ResponseBodypublic DBHackResponse<UserInfoVo> test2(String id , String name){UserInfoVo userInfoVo = new UserInf

GPT系列之:GPT-1,GPT-2,GPT-3详细解读

一、GPT1 论文:Improving Language Understanding by Generative Pre-Training 链接:https://cdn.openai.com/research-covers/languageunsupervised/language_understanding_paper.pdf 启发点:生成loss和微调loss同时作用,让下游任务来适应预训

Maven(插件配置和生命周期的绑定)

1.这篇文章很好,介绍的maven插件的。 2.maven的source插件为例,可以把源代码打成包。 Goals Overview就可以查看该插件下面所有的目标。 这里我们要使用的是source:jar-no-fork。 3.查看source插件的example,然后配置到riil-collect.xml中。  <build>   <plugins>    <pl

Java基础回顾系列-第七天-高级编程之IO

Java基础回顾系列-第七天-高级编程之IO 文件操作字节流与字符流OutputStream字节输出流FileOutputStream InputStream字节输入流FileInputStream Writer字符输出流FileWriter Reader字符输入流字节流与字符流的区别转换流InputStreamReaderOutputStreamWriter 文件复制 字符编码内存操作流(