Vue
Vue简介
Vue 核心
初识 Vue
- 想让Vue工作,就必须创建一个Vue实例,且要传入一个配置对象;
new Vue({ el:'#demo', data:{ //data中用于存储数据,数据供el所指定的容器去使用,值我们暂时先写成一个对象。 name:'atguigu', address:'北京' } })
参数说明:
- el用于指定当前Vue实例为哪个容器服务,值通常为css选择器字符串。也可以是以原生JS的方法获得的DOM元素。比如:
el:document.getElementById("root")
- data中用于存储数据,数据供el所指定的容器去使用,值可以是对象或函数的形式,常用函数的形式
- root容器里的代码依然符合html规范,只不过混入了一些特殊的Vue语法;
- root容器里的代码被称为【Vue模板】;
- Vue实例和容器是一一对应的(不是一对多或多对一的关系);
- 真实开发中只有一个Vue实例,并且会配合着组件一起使用;
- {{xxx}}中的xxx要写js表达式,且xxx可以自动读取到data中的所有属性;
注意区分:js表达式 和 js代码(语句)- 表达式:一个表达式会产生一个值(包括undefined),可以放在任何一个需要值的地方:
(1). a
(2). a+b
(3). demo(1)
(4). x === y ? 'a' : 'b' - js代码(语句)
(1). if(){}
(2). for(){}
- 表达式:一个表达式会产生一个值(包括undefined),可以放在任何一个需要值的地方:
- 一旦data中的数据发生改变,那么页面中用到该数据的地方也会自动更新;
<!DOCTYPE html> <html> <head> <meta charset="UTF-8" /> <title>初识Vue</title> <!-- 引入Vue --> <script type="text/javascript" src="../js/vue.js"></script> </head> <body> <!-- 准备好一个容器 --> <div id="demo"> <h1>Hello,{{name.toUpperCase()}},{{address}}</h1> </div> <script type="text/javascript" > Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。 //创建Vue实例 new Vue({ el:'#demo', //el用于指定当前Vue实例为哪个容器服务,值通常为css选择器字符串。 data:{ //data中用于存储数据,数据供el所指定的容器去使用,值我们暂时先写成一个对象。 name:'atguigu', address:'北京' } }) </script> </body> </html>
Vue.config 是一个对象,包含 Vue 的全局配置。可以在启动应用之前修改下列 property
productionTip
- 类型:boolean
- 默认值:true
- 用法:设置为 false 以阻止 vue 在启动时生成生产提示。
模板语法
html 中包含了一些 JS 语法代码,语法分为两种,分别为:
- 插值语法(双大括号表达式)
- 指令(以 v-开头)
Vue模板语法有2大类:
- 插值语法:
功能:用于解析标签体内容。
写法:{{xxx}}
,xxx是js表达式,且可以直接读取到data中的所有属性。 - 指令语法:
功能:用于解析标签(包括:标签属性、标签体内容、绑定事件.....)。
举例:v-bind:href="xxx"
或 简写为:href="xxx"
,xxx同样要写js表达式,且可以直接读取到data中的所有属性。
备注:Vue中有很多的指令,且形式都是:v-????,只是v-bind:href="xxx"
可以简写为:href="xxx"
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Document</title> <script type="text/javascript" src="../js/vue.js"></script> </head> <body> <div id="root"> <!-- 插值语法只能解析标签体内容,不能解析标签属性内容,所以href的值就为"{{url}}" --> <a href="{{url}}">点我去{{name}}学习1</a> <!-- 要想解析标签属性内容可以用v-bind,这里是简写形式 --> <a :href="url">点我去{{name}}学习2</a> </div> <script type="text/javascript" > new Vue({ el:'#root', data:{ name:'jack', // 同名属性写在同一级的话后面的属性会覆盖前面的,将同名属性写在不同层级不会互相影响 name:'尚硅谷', url:'http://www.atguigu.com', } }) </script> </body> </html>
<!DOCTYPE html> <html> <head> <meta charset="UTF-8" /> <title>模板语法</title> <!-- 引入Vue --> <script type="text/javascript" src="../js/vue.js"></script> </head> <body> <!-- 准备好一个容器--> <div id="root"> <h1>插值语法</h1> <h3>你好,{{name}}</h3> <hr/> <h1>指令语法</h1> <a v-bind:href="school.url.toUpperCase()" x="hello">点我去{{school.name}}学习1</a> <a :href="school.url" x="hello">点我去{{school.name}}学习2</a> </div> </body> <script type="text/javascript"> Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。 new Vue({ el:'#root', data:{ name:'jack', school:{ // 同名属性写在同一级的话后面的属性会覆盖前面的,将同名属性写在不同层级不会互相影响 name:'尚硅谷', url:'http://www.atguigu.com', } } }) </script> </html>
数据绑定
Vue中有2种数据绑定的方式:
- 单向数据绑定
- 语法:v-bind:href ="xxx" 或简写为 :href
- 特点:数据只能从 data 流向页面
- 双向数据绑定
- 语法:v-mode:value="xxx" 或简写为 v-model="xxx"
- 特点:数据不仅能从 data 流向页面,还能从页面流向 data
备注:
- 双向绑定一般都应用在表单类元素上(如:input、select等),就是有value属性的元素,即可以输入值的元素(包括单选按钮,复选框等)
- v-model:value 可以简写为 v-model,因为v-model默认收集的就是value值。
<body> <!-- Vue中有2种数据绑定的方式: 1.单向绑定(v-bind):数据只能从data流向页面。 2.双向绑定(v-model):数据不仅能从data流向页面,还可以从页面流向data。 备注: 1.双向绑定一般都应用在表单类元素上(如:input、select等) 2.v-model:value 可以简写为 v-model,因为v-model默认收集的就是value值。 --> <!-- 准备好一个容器--> <div id="root"> <!-- 普通写法 --> <!-- 单向数据绑定:<input type="text" v-bind:value="name"><br/> 双向数据绑定:<input type="text" v-model:value="name"><br/> --> <!-- 简写 --> 单向数据绑定:<input type="text" :value="name"><br/> 双向数据绑定:<input type="text" v-model="name"><br/> <!-- 如下代码是错误的,因为v-model只能应用在表单类元素(输入类元素)上 --> <!-- <h2 v-model:x="name">你好啊</h2> --> </div> </body> <script type="text/javascript"> Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。 new Vue({ el:'#root', data:{ name:'尚硅谷' } }) </script>
单向数据绑定
el和data的2种写法
- el有2种写法
(1).new Vue时候配置el属性。
const v = new Vue({ el:'#root', //第一种写法, 在创建Vue实例对象时就指定el data:{ name:'尚硅谷' } })
(2).先创建Vue实例,随后再通过vm.$mount('#root')指定el的值。mount此处意为挂载
// 创建Vue实例时先不指定el const v = new Vue({ data:{ name:'尚硅谷' } }) ... v.$mount('#root') //第二种写法, 在适当的时候再挂载el
- data有2种写法
(1).对象式
new Vue({ el:'#root', //data的第一种写法:对象式 data:{ name:'尚硅谷' }
(2).函数式:data属性值是一个函数(不要是箭头函数,以免造成this的混乱),函数的返回值是与对象式中的data等效的对象, 例如
data:function(){ ... return {...} }
可简写成
data(){ ... return {...} }
函数中的this是Vue实例对象
如何选择:目前哪种写法都可以,以后学习到组件时,data必须使用函数式,否则会报错。
- 一个重要的原则:
由Vue管理的函数,一定不要写箭头函数,一旦写了箭头函数,this就不再是Vue实例了。
MVVM 模型
- M:模型(Model) :对应 data 中的数据
- V:视图(View) :模板html
- VM:视图模型(ViewModel) : Vue 实例对象
特点
- data中所有的属性,最后都出现在了vm身上。
- vm身上所有的属性 及 Vue原型上所有属性,在Vue模板中都可以直接使用。
<body> <!-- 准备好一个容器--> <div id="root"> <h1>学校名称:{{name}}</h1> <h1>学校地址:{{address}}</h1> <h1>测试一下1:{{1+1}}</h1> <!-- Vue模板(就是与Vue实例绑定的DOM)可以直接读取Vue实例及其原型链上的属性 --> <h1>测试一下2:{{$options}}</h1> <h1>测试一下3:{{$emit}}</h1> <h1>测试一下4:{{_c}}</h1> </div> </body> <script type="text/javascript"> Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。 const vm = new Vue({ el:'#root', data:{ // data中的属性添加到了Vue实例中 name:'尚硅谷', address:'北京', } }) console.log(vm) </script>
数据代理
Object.defineProperty()
详见MDN
Object.defineProperty() 方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象
该方法允许精确地添加或修改对象的属性。通过赋值操作添加的普通属性是可枚举的,在枚举对象属性时会被枚举到(for...in 或 Object.keys方法),可以改变这些属性的值,也可以删除这些属性。这个方法允许修改默认的额外选项(或配置)。默认情况下,使用 Object.defineProperty() 添加的属性值是不可修改(immutable)、不可删除且不可枚举的。
备注:应当直接在 Object 构造器对象上调用此方法,而不是在任意一个 Object 类型的实例上调用
语法
Object.defineProperty(obj, prop, descriptor)
参数
obj: 要定义属性的对象。
prop:要定义或修改的属性的名称或 Symbol
descriptor:要定义或修改的属性描述符(就是一个配置对象)。对象里目前存在的属性描述符有两种主要形式:数据描述符和存取描述符。数据描述符是一个具有值的属性,该值可以是可写的,也可以是不可写的。存取描述符是由 getter 函数和 setter 函数所描述的属性。一个描述符只能是这两者其中之一;不能同时是两者
返回值:被传递给函数的对象
descriptor中的配置项
- value, 即要配置的obj对象中prop的属性值
- writable,控制属性是否可以被修改,默认值是false即不能被重新赋值
var o = {}; // 创建一个新对象 Object.defineProperty(o, 'a', { value: 37, writable: false }); console.log(o.a); // logs 37 o.a = 25; // No error thrown // (it would throw in strict mode, // even if the value had been the same) console.log(o.a); // logs 37. The assignment didn't work.
- enumerable 默认是false,定义了该属性是否可以在
for...in
循环和Object.keys()
中被枚举
var o = {}; Object.defineProperty(o, "a", { value : 1, enumerable: true }); Object.defineProperty(o, "b", { value : 2, enumerable: false }); Object.defineProperty(o, "c", { value : 3 }); // enumerable 默认为 false o.d = 4; // 如果使用直接赋值的方式创建对象的属性,则 enumerable 为 true for (var i in o) { console.log(i); } // logs 'a' and 'd' (in undefined order) Object.keys(o); // ['a', 'd']
- configurable 默认值为false,表示对象的属性是否可以被删除,以及除 value 和 writable 外的其他配置项是否可以被修改
var o = {}; Object.defineProperty(o, 'a', { get() { return 1; }, configurable: false }); Object.defineProperty(o, 'a', { configurable: true }); // throws a TypeError Object.defineProperty(o, 'a', { enumerable: true }); // throws a TypeError Object.defineProperty(o, 'a', { set() {} }); // throws a TypeError (set was undefined previously) Object.defineProperty(o, 'a', { get() { return 1; } }); // throws a TypeError // (even though the new get does exactly the same thing) Object.defineProperty(o, 'a', { value: 12 }); // throws a TypeError // ('value' can be changed when 'configurable' is false but not in this case due to 'get' accessor) console.log(o.a); // logs 1 delete o.a; // Nothing happens console.log(o.a); // logs 1
如果 o.a 的 configurable 属性为 true,则不会抛出任何错误,并且,最后,该属性会被删除
- get() :每次读取prop属性时,get函数(getter)就会被调用,且返回值就是prop属性的值
- set() :每次修改person的age属性时,set函数(setter)就会被调用,该方法接受一个参数(也就是被赋予的新值)
<body> <script type="text/javascript" > let number = 18 let person = { name:'张三', sex:'男', } Object.defineProperty(person,'age',{ // value:18, // enumerable:true, //控制属性是否可以枚举,默认值是false // writable:true, //控制属性是否可以被修改,默认值是false // configurable:true //控制属性是否可以被删除,默认值是false //当有人读取person的age属性时,get函数(getter)就会被调用,且返回值就是age的值 get(){ console.log('有人读取age属性了') return number }, //当有人修改person的age属性时,set函数(setter)就会被调用,且会收到修改的具体值 set(value){ console.log('有人修改了age属性,且值是',value) number = value } }) // console.log(Object.keys(person)) console.log(person) </script> </body>
数据代理
通过Object.defineProperty()让obj中的x属性映射到obj2中(双向映射的关系),同时修改obj2中的x属性也会修改obj中的x属性, 这类现象叫做“数据代理”
let obj = {x:100} let obj2 = {y:200} Object.defineProperty(obj2,'x',{ get(){ return obj.x }, set(value){ obj.x = value } })
Vue中的数据代理
- Vue中的数据代理:
通过vm对象来代理data对象中属性的操作(读/写) - Vue中数据代理的好处:
更加方便的操作data中的数据, 即可以直接用data对象中的属性名,而
不用通过_data.属性名
来操作属性 - 基本原理:
通过Object.defineProperty()把data对象中所有属性添加到vm上。
为每一个添加到vm上的属性,都指定一个getter和setter。
在getter和setter内部去操作(读/写)data中对应的属性。
本文作者:Code6E
本文链接:https://www.cnblogs.com/road2code/p/17149163.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步