Vue基础知识-单向绑定v-bind、双向绑定v-model、插值语法{{}}、Object.defineProperty实现数据代理
一、Vue 基础数据绑定示例
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><script src="../js/vue.js"></script><script>//关闭默认提示Vue.config.productionTip = false//shift+刷新=强制刷新</script></head>
<body><div id="root"><h2>{{person.name}}</h2> <!-- {{}}里面写表达式,特殊的字符会从Vue实例里找。一般用于标签体内(单向绑定) --><a :href="href">百度</a><br> <!-- 完整写法为v-bind:href。一般用于标签属性,因为标签属性一般不会改 --><input type="text" :value="username"/> <!-- 单向绑定(数据从data流向页面):表单数据改而username不改,username改表单数据改 --><input type="text" v-model="username2"/> <!-- 双向绑定(数据在页面和data可双向流):表单数据和username同步改。完整写法为v-model:value。一般用于输入类表单。默认收集value属性--></div><script>const vm = new Vue({el:"#root", //为<div id="root">容器服务,其之外的标签访问不了data。容器和Vue实例一一对应/* 第一种写法data:{person:{name:"th",age:18},username:"th",username2:"th2",href:"https://www.baidu.com"},*///第二种写法(学组件必须用)。注意data方法由Vue来调用data(){ // 完整写法:data:function(){} 。箭头函数写法data:()=>{}。注意箭头函数没有this,则向外找,找到了windowsreturn { //因此,Vue所管理的函数建议不写箭头函数。保证他的this是Vue实例即可person:{name:"th",age:18},username:"th",username2:"th2",href:"https://www.baidu.com"}}})// vm.$mount('#root') 第二种挂载方式/* MVVM:model:data中数据 view:模板代码 vm的所有属性及Vue原型(Prototype)上的所有属性。在Vue模块中可以直接使用。data里的数据(即vm._data)通过数据代理成为了vm属性vm:Vue实例*/</script>
</body>
</html>
代码说明
三种数据绑定方式
- 文本插值:
{{person.name}}
实现标签体内数据展示 - 属性绑定:
:href="href"
等价于v-bind:href
,动态设置 HTML 属性 - 双向绑定:
v-model="username2"
实现表单输入与 data 数据同步
- 文本插值:
data 的两种写法
- 对象式写法(注释中):适用于简单场景
- 函数式写法(实际使用):组件开发必须使用,确保每个实例拥有独立数据
MVVM 模式
- 通过 Vue 实例(vm)实现数据(model)与视图(view)的双向绑定
- 数据代理机制让开发者可直接通过
vm.属性
访问数据
二、JavaScript 数据代理原理示例
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head>
<body><script>let person = {name:'zhangsan'}Object.defineProperty(person,'sex',{value:'男',enumerable:true, //表示可枚举(默认为false),即Object.keys(person)可以拿到sexwritable:true ,//表示可被修改(默认为false),即person.sex = '女' 能够生效configurable:true //表示可被删除(默认为false),即delete person.sex能够生效})//数据代理:通过一个对象代理另一个对象中属性的读写操作。//例子:让templateAge代理person的x。即age读写时本质都操作templateAge即可,即重写age的get和set let templateAge;Object.defineProperty(person,'age',{get(){ //当读取时调用return templateAge},set(value){ //当修改时调用,且传入修改的值templateAge = value}})// Vue中的数据代理:使用vm对象代理vm._data对象中属性的读写。// 好处:方便,使用vm.即可访问_data中的数据而非vm._data. // 原理:使用 Object.defineProperty方法把vm._data对象里的属性添加到vm对象里的属性。// 为啥多一层_data? Vue规定:为_data里属性添加react式的getter和setter实现双向数据绑定。let vm = {_data:{x:1}}Object.defineProperty(vm,'x',{ //vm.x即可操作vm._data.xget(){return vm._data.x},set(value){vm._data.x=value}})</script>
</body>
</html>
数据代理核心原理
Object.defineProperty 关键参数
value
:属性默认值get/set
:属性读写时的回调函数enumerable
:是否可被枚举(如通过 for...in 遍历)writable
:是否可被修改configurable
:是否可被删除或重新定义
数据代理本质
通过一个对象(代理对象)控制另一个对象(目标对象)的属性访问:Object.defineProperty(代理对象, '属性名', {get() { return 目标对象.属性名 },set(value) { 目标对象.属性名 = value } })
Vue 数据代理设计
- 实际数据存储在
_data
中 - 通过代理让
vm.属性
直接操作_data.属性
- 为
_data
属性添加响应式 getter/setter,实现数据变化监听
- 实际数据存储在