Vue:模板 MVVM
Vue:模板 & MVVM
- 模板
- 插值语法
- 指令语法
- MVVM
- defineProperty
- 数据代理
模板
Vue
实例绑定一个容器,想要向容器中填入动态的值,就需要使用模板语法。模板语法分为插值语法
和指令语法
。
插值语法
插值语法很简单,使用{{}}
包含一个表达式,Vue
会把表达式的结果替代这个值渲染到HTML
中。
示例:
<div id="root"><h3>hello,{{name}}</h3>
</div>
<script type="text/javascript">new Vue({el:'#root',data:{name:'jack',}})
</script>
以上代码,最终会生成hello,jack
标题,{{name}}
被替换为了data.name
。
此外,任意表达式都可以填入{{}}
中,比如:
<div id="root"><h3>hello,{{1 + 1}}</h3><h3>hello,{{x === y ? 'a' : 'b'}}</h3>
</div>
比如{{1 + 1}}
最终会变成2
,三元表达式会进行计算,或者说函数调用也可以在{{}}
内部执行。
另外的,{{}}
内的表达式,可以读取到Vue
示例的data
下的所有属性。
指令语法
插值语法能处理的情况是非常有限的,比如标签属性。
现在有一个<a>
标签,要动态的指定url
,如果使用插值语法,可能写出如下内容:
<div id="root"><a href="{{addr.url}}">{{addr.name}}</a>
</div>
<script type="text/javascript">new Vue({el:'#root',data:{addr:{name:'百度',url:'http://www.baidu.com',}}})
</script>
但是这是一个错误的语法,{{}}
作为标签属性时,不会被解析。
此时就要使用指令语法,v-bind
指令可以将一个属性值解析为表达式。
<div id="root"><a v-bind:href="addr.url">{{addr.name}}</a>
</div>
以上代码中,herf
属性前面加上了v-bind:
,那么后面的""
内部不再被解析为字符串,而是当作表达式处理,此时addr.url
就会被解析了。
一个v-bind
只能作用于其后面的那个属性,比如以下情况:
<div id="root"><a v-bind:href="addr.url" id="addr.name">{{addr.name}}</a>
</div>
在id="name"
中,addr.name
不会被当作表达式,而是当作字符串,因为其前面没用v-bind
指令。
v-bind
指令可以简写为一个冒号:
。
<div id="root"><a :href="addr.url">{{addr.name}}</a>
</div>
- 数据绑定
刚才的v-bind
称为单向数据绑定,简单来说就是如果Vue
实例中的属性值改变了,那么HTML
的内容也会改变。但是如果HTML
的内容改变了,Vue
实例的内容不会改变。
示例:
<div id="root">单向数据绑定:<input type="text" :value="inner"><br/>
</div>
<script type="text/javascript">new Vue({el:'#root',data:{inner:'hello world'}})
</script>
这是一个输入框,输入框的value
属性被绑定为了inner
的内容。
初始时,inner
和输入框的内容相同,尝试修改inner
的值:
修改后,输入框的内容也随之改变了。
但是如果修改输入框的内容:
此时inner
的内容不会改变,这就是单向数据绑定,Vue
实例的值会影响HTML
,但是HTML
不会影响Vue
实例。
指令v-model
可以使用双向数据绑定:
<div id="root">双向数据绑定:<input type="text" v-model:value="inner"><br/>
</div>
此时修改输入框,也会反过来修改Vue
实例的值:
但是不是所有标签都可以使用v-model
,只有可以输入元素,类似表单的元素可以使用,其他标签使用会导致报错,并且标签会丢失。
v-model:
也可以简写,因为v-model:
后面的属性往往是value
,表示元素内容,所以可以省略:value
,直接写为v-model
:
<div id="root">双向数据绑定:<input type="text" v-model="inner"><br/>
</div>
MVVM
MVVM
是一种软件开发模型,在Vue
设计时参考了这个模型,其分为三个组成部分:
Model
:模型View
:视图ViewModel
:视图模型
Model
就是一个JavaScript
的表达式,简单来说就是数据,比如在{{}}
中包含一个表达式,在v-bind
后面的" "
内部的表达式,这些表达式都会产生一个值,变成具体的数据。
View
对应上图中最左侧的DOM
,它表示一个可以被用户看到的页面,这个页面通过Vue
解析产生。
ViewModel
是上图的中间部分,它表示Vue
实例对象,这也是整个MVVM
的核心,其分为两个区域。
首先是Data Bindings
数据绑定,它接收Model
产生的值,并把它填入到View
视图中,这样就产生了最终的页面。这对应了之前的v-bind
指令,或者{{}}
插值,他们都是接收JavaScript
表达式产生的值,并填入到元素中。
另一个是DOM Listeners
元素监听,它监听页面中的元素,当元素发生变化时,返过来影响Model
内部的值。这对应的了v-model
双向数据绑定,当DOM
元素发生更改时,修改Vue.data
的内容。
在Vue
中,JavaScript
表达式可以看到Vue
实例的所有属性和方法,包括原型链。
输出一下Vue
实例:
const vm = new Vue({el:'#root',data:{name:'hello world',num: 123}
})
console.log(vm)
由于Vue
实例在MVVM
中对应VM
,所以接收时常把变量命名为vm
。
输出结果:
可以看到,name
、num
这两个属性最后都进入到了Vue
实例中,构造时会把data
下面的所有属性都添加到Vue
实例中,这就是为什么在{{}}
内部可以看到data
下面的数据,
仔细看name
、num
的属性值是(...)
,这涉及到数据代理的问题。
defineProperty
Object.defineProperty
可以给一个对象添加指定的值,并且可以进行属性的复杂配置。
语法:
Object.defineProperty(对象, 属性, {配置对象})
对象
:被修改的对象属性
:要添加的属性{配置对象}
:添加属性相关的配置
例如给一个对象"张三"
添加一个age
属性:
let person = {name:'张三',sex:'男',
}Object.defineProperty(person,'age',{value:18,enumerable:true, //控制属性是否可以枚举,默认值是falsewritable:true, //控制属性是否可以被修改,默认值是falseconfigurable:true //控制属性是否可以被删除,默认值是false
})
在配置对象中,value
就是配置的属性值,剩下三个属性用于对元素做一些限制。
比如说enumerable
控制元素是否可以被遍历,如果为false
,那么for in
语法就无法获取到这个值,或者通过keys
方法无法获得属性名。
后两个比较好理解,就是能否修改与删除。
这些都不是重点,在配置对象中还可以配置函数,其中set
和get
方法非常重要。
get
方法在该属性被读取时调用,并且读取元素值时,返回指定值。
Object.defineProperty(person,'age',{get(){console.log('有人读取age属性了')return 123}
})
输出结果:
此时可以看到,age
属性的值变成了(...)
,表示暂时未知。当访问person.age
,调用了get
函数并拿到了返回值123
。
注意:get
方法和value
属性不能同时设置。
set
方法在该属性被设置时调用,接收一个参数value
,这就是要设置的值。
实例:
Object.defineProperty(person,'age',{set(value){console.log('有人修改了age属性,值是',value)number = value}
})
输出结果:
在修改值时,调用了对应的set
函数。
注意:set
不能和writable
属性一起指定。
基于这两个特性,它可以完成一个功能:让一个对象外部的变量与该属性完全同步。
let number = 18
let person = {name:'张三',sex:'男',
}Object.defineProperty(person,'age',{get(){return number},set(value){number = value}
})
以上代码,实现了person.age
与变量number
的完全同步。当每次读取age
时,返回number
的值,每次设置age
时,把number
一起修改。
基于以上操作,就可以完成数据代理。
数据代理
数据代理:通过一个对象代理对另一个对象中属性的操作
示例:
let A = {x:100}
let B = {}Object.defineProperty(B,'x',{get(){return A.x},set(value){A.x = value}
})
以上就是一个数据代理,A.x
与B.x
是完全同步的,操作B.x
对应的A.x
也会修改,任何时候A.x === B.x
。
现在再回看之前Vue
实例中name
和num
的变量值为(...)
,这其实就是一个数据代理。
在Vue
实例的底部,可以看到四个方法:
这四个方法分别就是name
和num
的get
和set
,此处将vm.name
和vm.num
进行了数据代理,代理到data.name
和data.num
,这样可以保证vm
和构造时传入的data
完全同步。
而传入data
时,有可能传了个匿名对象,data
本身也要进行保存,其实vm
把data
保存为了一个vm._data
的对象。
真正被代理的其实是vm._data
,如果不做这层代理,那么用户访问数据时就要写{{ _data.name }}
、{{ _data.num }}
,这样有点麻烦,因此做了依次数据代理,将他直接放到vm
下,这样就可以直接访问了。
另外的,可以发现在_data
中,这两个属性的值也是(...)
,看着很想数据代理,但这并不是。这是数据劫持,当_data
的数据发生改变,就要渲染到HTML
页面中,这个过程是由数据劫持完成的。
相关文章:

Vue:模板 MVVM
Vue:模板 & MVVM 模板插值语法指令语法 MVVMdefineProperty数据代理 模板 Vue实例绑定一个容器,想要向容器中填入动态的值,就需要使用模板语法。模板语法分为插值语法和指令语法。 插值语法 插值语法很简单,使用{{}}包含一…...

Kafka 消息丢失如何处理?
今天给大家分享一个在面试中经常遇到的问题:Kafka 消息丢失该如何处理? 这个问题啊,看似简单,其实里面藏着很多“套路”。 来,咱们先讲一个面试的“真实”案例。 面试官问:“Kafka 消息丢失如何处理&#x…...

Mysql报错注入之floor报错详解
updatexml extractvalue floor 是mysql的函数 groupbyrandfloorcount 一、简述 利用 select count(),(floor(rand(0)2))x from table group by x,导致数据库报错,通过 concat 函数,连接注入语句与 floor(rand(0)*2)函数,实现将…...

EPS原理笔记
EPS UE(user equipment),移动用户设备 LTE(Long Term Evolution),无线接入网部分,E-UTRAN EPC(system Architecture Evolution、Evoloed Packet Core),核心网部分,主要包括MME、S-GW、P-GW、HSS,连接Intern…...

LeetCode 876. 链表的中间结点
题目描述: 给你单链表的头结点 head ,请你找出并返回链表的中间结点。 如果有两个中间结点,则返回第二个中间结点。 示例 1: 输入:head [1,2,3,4,5] 输出:[3,4,5] 解释:链表只有一个中间结点࿰…...

划界与分类的艺术:支持向量机(SVM)的深度解析
划界与分类的艺术:支持向量机(SVM)的深度解析 1. 引言 支持向量机(Support Vector Machine, SVM)是机器学习中的经典算法,以其强大的分类和回归能力在众多领域得到了广泛应用。SVM通过找到最优超平面来分…...
题目:100条经典C语言笔试题目(1-5)
题目: 1、请填写 bool , float, 指针变量 与“零值”比较的if 语句。 提示:这里“零值”可以是 0, 0.0 , FALSE 或者“空指针” 。例如 int 变量 n 与“零值”比较的 if 语句为: (1)请写出bool flag 与“零值”比较…...
python代码编写规范及注意事项
目录 1. 注意1.1 变量与常量解释:建议的修复: 1.2 Too many arguments 和 Too many local variables解决方案1. 减少参数数量2. 减少局部变量数量3. 调整 Pylint 配置 总结 1. 注意 1.1 变量与常量 解读下面的pylint问题 C0103: Constant name “file_p…...

【Linux】命令行参数 | 环境变量
🪐🪐🪐欢迎来到程序员餐厅💫💫💫 主厨:邪王真眼 主厨的主页:Chef‘s blog 所属专栏:青果大战linux 总有光环在陨落,总有新星在闪烁 前几天在搞硬件&…...

python 使用进程池并发执行 SQL 语句
这段代码使用了 Python 的 multiprocessing 模块来实现真正的并行处理,绕过 Python 的全局解释器锁(GIL)限制,从而在多核 CPU 上并发执行多个 SQL 语句。 from pyhive import hive import multiprocessing# 建立连接 conn hive.…...

我也谈AI
“随着人工智能技术的不断发展,我们已经看到了它在各行业带来的巨大变革。在医疗行业中,人工智能技术正在被应用于病例诊断、药物研发等方面,为医学研究和临床治疗提供了新的思路和方法;在企业中,人工智能技术可以通过…...

算法妙妙屋-------1.递归的深邃回响:二叉树的奇妙剪枝
大佬们好呀,这一次讲解的是二叉树的深度搜索,大佬们请阅 1.前言 ⼆叉树中的深搜(介绍) 深度优先遍历(DFS,全称为DepthFirstTraversal),是我们树或者图这样的数据结构中常⽤的⼀种…...

编写第一个 Appium 测试脚本:从安装到运行!
前言 最近接到一个测试项目,简单描述一下,需求就是:一端发送指令,另一端接受指令并处理指令。大概看了看有上百条指令,点点点岂不是废了,而且后期迭代,每次都需要点点点,想想就头大…...

mysql查表相关练习
作业要求: 单表练习: 1 . 查询出部门编号为 D2019060011 的所有员工 2 . 所有财务总监的姓名、编号和部门编号。 3 . 找出奖金高于工资的员工。 4 . 找出奖金高于工资 40% 的员工。 5 找出部门编号为 D2019090011 中所有财务总监,和…...

airtest+poco多脚本、多设备批处理运行测试用例自动生成测试报告
一:主要内容 框架功能、框架架构及测试报告效果 airtest安装、环境搭建 框架搭建、框架运行说明 框架源码 二:框架功能及测试报告效果 1. 框架功能: 该框架笔者用来作为公司的项目的前端自动化,支持pc和app,本文…...

Prometheus套装部署到K8S+Dashboard部署详解
1、添加helm源并更新 helm repo add prometheus-community https://prometheus-community.github.io/helm-charts helm repo update2、创建namespace kubectl create namespace monitoring 3、安装Prometheus监控套装 helm install prometheus prometheus-community/prome…...
python使用pymysql
为了封装这个数据库操作为一个通用方法,我们可以创建一个函数,该函数接受数据库连接参数(如主机名、用户名、密码、数据库名)、SQL语句以及必要的参数(用于参数化查询)。下面是一个简单的封装示例ÿ…...
Vue3 + TypeScript 组件和文件命名规范及 setup 导入顺序规范
前言 在 Vue3 项目中,合理的文件命名规范和导入顺序不仅有助于提高代码的可读性,还能增强团队协作的效率。特别是在使用 TypeScript 和 Composition API 的项目中,清晰的组件和文件结构尤为重要。本文将详细介绍 Vue3 TypeScript 项目中的组…...
netty之处理连接源码分析
写在前面 在这篇文章看了netty服务是如何启动的,服务启动成功后,也就相当于是迎宾工作都已经准备好了,那么当客人来了怎么招待客人呢?也就是本文要看的处理连接的工作。 1:正文 先启动源码example模块的echoserver&a…...
Dockerfile文件编写
1、打nginx原始包 登录后复制 ROM nginxENV LANG zh_CN.UTF-8 ENV LC_ALL zh_CN.UTF-8 ENV TZ Asia/Singapore# 设置时区,同样保持在一层 RUN ln -sf /usr/share/zoneinfo/${TZ} /etc/localtime && \echo "${TZ}" > /etc/timezoneRUN apt-get …...
CVPR 2025 MIMO: 支持视觉指代和像素grounding 的医学视觉语言模型
CVPR 2025 | MIMO:支持视觉指代和像素对齐的医学视觉语言模型 论文信息 标题:MIMO: A medical vision language model with visual referring multimodal input and pixel grounding multimodal output作者:Yanyuan Chen, Dexuan Xu, Yu Hu…...
椭圆曲线密码学(ECC)
一、ECC算法概述 椭圆曲线密码学(Elliptic Curve Cryptography)是基于椭圆曲线数学理论的公钥密码系统,由Neal Koblitz和Victor Miller在1985年独立提出。相比RSA,ECC在相同安全强度下密钥更短(256位ECC ≈ 3072位RSA…...

Mac软件卸载指南,简单易懂!
刚和Adobe分手,它却总在Library里给你写"回忆录"?卸载的Final Cut Pro像电子幽灵般阴魂不散?总是会有残留文件,别慌!这份Mac软件卸载指南,将用最硬核的方式教你"数字分手术"࿰…...

UR 协作机器人「三剑客」:精密轻量担当(UR7e)、全能协作主力(UR12e)、重型任务专家(UR15)
UR协作机器人正以其卓越性能在现代制造业自动化中扮演重要角色。UR7e、UR12e和UR15通过创新技术和精准设计满足了不同行业的多样化需求。其中,UR15以其速度、精度及人工智能准备能力成为自动化领域的重要突破。UR7e和UR12e则在负载规格和市场定位上不断优化…...

ABAP设计模式之---“简单设计原则(Simple Design)”
“Simple Design”(简单设计)是软件开发中的一个重要理念,倡导以最简单的方式实现软件功能,以确保代码清晰易懂、易维护,并在项目需求变化时能够快速适应。 其核心目标是避免复杂和过度设计,遵循“让事情保…...

保姆级教程:在无网络无显卡的Windows电脑的vscode本地部署deepseek
文章目录 1 前言2 部署流程2.1 准备工作2.2 Ollama2.2.1 使用有网络的电脑下载Ollama2.2.2 安装Ollama(有网络的电脑)2.2.3 安装Ollama(无网络的电脑)2.2.4 安装验证2.2.5 修改大模型安装位置2.2.6 下载Deepseek模型 2.3 将deepse…...

JVM 内存结构 详解
内存结构 运行时数据区: Java虚拟机在运行Java程序过程中管理的内存区域。 程序计数器: 线程私有,程序控制流的指示器,分支、循环、跳转、异常处理、线程恢复等基础功能都依赖这个计数器完成。 每个线程都有一个程序计数…...

人工智能(大型语言模型 LLMs)对不同学科的影响以及由此产生的新学习方式
今天是关于AI如何在教学中增强学生的学习体验,我把重要信息标红了。人文学科的价值被低估了 ⬇️ 转型与必要性 人工智能正在深刻地改变教育,这并非炒作,而是已经发生的巨大变革。教育机构和教育者不能忽视它,试图简单地禁止学生使…...

【JVM】Java虚拟机(二)——垃圾回收
目录 一、如何判断对象可以回收 (一)引用计数法 (二)可达性分析算法 二、垃圾回收算法 (一)标记清除 (二)标记整理 (三)复制 (四ÿ…...
Python 高效图像帧提取与视频编码:实战指南
Python 高效图像帧提取与视频编码:实战指南 在音视频处理领域,图像帧提取与视频编码是基础但极具挑战性的任务。Python 结合强大的第三方库(如 OpenCV、FFmpeg、PyAV),可以高效处理视频流,实现快速帧提取、压缩编码等关键功能。本文将深入介绍如何优化这些流程,提高处理…...