Vue 注意事项 模板语法 单双向绑定 语法格式 MVVM框架 Object.defineProperty和数据代理操作
Posted IT_Holmes
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Vue 注意事项 模板语法 单双向绑定 语法格式 MVVM框架 Object.defineProperty和数据代理操作相关的知识,希望对你有一定的参考价值。
文章目录
1.Vue 注意事项
1. 容器 和 实例
这里牢记一点:
多个容器对应一个实例,多个实例对应一个容器都是错误的!!!
容器和Vue实例必须是一一对应的关系,不能混杂。
2. 区分好js代码 和 js表达式
就算在Vue实例中,没有表现特定属性或方法,在一些js表达式也是可以使用的。如下:{{Date.now()}} 。
解释一下js表达式和js代码区别:
js代码直接定义了走向什么的,例如:if,for等等语句。
js表达式,一个表达式会产生一个值,例如:a+b,a,三元表达式,函数表达式(上面的Date.now(),就是一个函数调用表达式)等,都是js表达式。
3. 真是开发中只有一个Vue实例
真是开发中只有一个Vue实例,并且配合一些组件。
4. {{xxx}} 中要写js代码或js表达式
{{xxx}} 中的xxx要写js表达式,且xxx会自动读取到data中的所有属性。
此外,就是要尽量使用开发版本的Vue,生产版本的Vue错误提示不会很明显。
2. Vue 模板语法
2.1 {{xxx}} 插值语法
就是{{xxx}},这种语法就是插值语法。
2.2 v-??? 指令语法
指令语法功能:
用于解析标签,包括:标签属性、标签体内容、绑定时间等等,下面的v-bind(对标签属性)只是一个例子。
v-bind能够将所对应的属性中的引号里面的值,当成js表达式来执行。此外,v-bind可以给任何一个属性标签来动态绑定,大多数用在href上面。
v-bind:href=“xxx” 或 简写为 :href=“xxx” ,当然这里的xxx只能写js表达式。
源码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
</head>
<body>
<div id="root">
<!-- 差值语法显示 -->
<h1>差值语法</h1>
<h3>你好,{{name}}</h3>
<hr>
<!-- 指令语法显示 -->
<h1>指令语法</h1>
<!-- v-bind可以将引号中url当成表达式来执行,而不是字符串。 -->
<a v-bind:href="school.url.toUpperCase()">百度1</a>
<a :href="school.url">百度2</a>
</div>
<script>
Vue.config.productionTip = false;
new Vue({
el:"#root",
data:{
name:"张三",
school:{
url:"http://www.baidu.com",
name:"李四"
}
}
});
</script>
</body>
</html>
提示:
Vue中有很多的指令,且形式都是v-???,这里的v就是Vue,v-bind只是其中的一员,指令语法还有很多的。当然指令语法也可以使用其他js表达式,如上面的toUpperCase()。
像这种镶嵌格式的,就像下图表示:
3. 单向绑定和双向绑定
v-bind是单向绑定,v-model是双向绑定。这里的绑定是和Vue开发者工具里的data来绑定的。
注意:
v-model只能应用在表单元素(输入元素)上 ,简而言之就是要有value值。
Vue的两种绑定方式总结:Vue的两种绑定方式的简写:
1. v-bind: 可以简写为: 。
2. v-model:value = "xxx"可以简写为v-model = “xxx” 。
源码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
</head>
<body>
<div id="root">
<!-- v-bind是单项绑定 -->
单项数据绑定:<input type="text" v-bind:value="name">
单项数据绑定:<input type="text" :value="name">
<br>
<!-- v-model是双向绑定 -->
双项数据绑定:<input type="text" v-model:value="name">
双项数据绑定:<input type="text" v-model="name">
<!-- 如下代码时错误的,因为v-model只能应用在表单元素(输入元素)上 ,简而言之就是要有value值。-->
<h1 v-medolx="111">你好啊</h1>
</div>
<script>
Vue.config.productionTip = false;
const vm = new Vue({
el:"#root",
data:{
name:"张三"
}
});
</script>
</body>
</html>
4. el和data的两种写法方式
4.1 介绍 Vue实例对象一些方法
这里我们打印一个Vue的实例,来看看里面的内容,见图。
4.2 el的两种写法方式
第一种是直接用el来定义,第二种是$mount()方法来实现。见源码。
源码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
</head>
<body>
<div id="root">
<h1>{{name}}</h1>
</div>
<script>
Vue.config.productionTip = false;
const vm = new Vue({
// el:'',
data:{
name:"张三"
}
})
console.log(vm);
//$mount比el:'xxx'更加灵活一些,就像下面延迟两秒一样。
setTimeout(()=>{
vm.$mount('#root');//$mount可以代表el:'xxx'来操作。
},2000);
</script>
</body>
</html>
4.3 data 两种写法方式
data的两种写法:第一种是对象式,第二种是函数式。
注意函数式,非常重要,组件必须用到函数式,此外data函数可以简化,并且这里不能使用箭头函数,因为这里的this指向必须是Vue实例对象!
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
</head>
<body>
<div id="root">
<h1>{{name}}</h1>
</div>
<script>
Vue.config.productionTip = false;
const vm = new Vue({
el:'#root',
// data的第一种写法:对象式
// data:{
// name:"张三"
// }
// data的第二种写法:函数式 ,学习组件很重要!!
/*
data:function(){
console.log(this);
return{
name:"张三"
}
}
*/
// 可以简化上面的写法为:
data(){
console.log(this); //这里的this指向Vue实例对象,因为以后要用到Vue实例对象,所以不能使用箭头函数,否则指向window全局。
return {
name:"张三"
}
}
})
</script>
</body>
</html>
5. 了解Vue的MVVM架构
DOM Listeners :模块监听。
Data Bindings : 数据绑定。
这俩个都是很重要的存在记住!
通过上图,可以了解到MVVM整体的架构。
注意:
1. data中所有的属性,最后都出现在了vm实例对象上面。
2. vm升上所有的属性和Vue原型上所有的属性,都可以直接在Vue模板中使用。
见源码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.14/dist/vue.js"></script>
</head>
<body>
<div id="root">
<h1>学校名称:{{name}}</h1>
<h1>学校地址:{{address}}</h1>
<h1>1+1 为什么等于 {{1+1}} ?</h1>
<h1>测试Vue的$options,{{$options}}</h1> <!--查看测试Vue的$option内置函数 -->
<h1>测试Vue原型$emit,{{$emit}}</h1> <!--查看测试Vue的$emit原型函数 -->
<h1>测试没有$开头的 _c,{{_c}}</h1> <!--查看测试Vue的 _C 函数 -->
</div>
<script>
Vue.config.productionTip = false;
const vm = new Vue({
// el:'#root',
//data中的内容,会传送到vm身上。
data:{
name:"清华大学",
address:"北京"
}
})
vm.$mount("#root");
console.log(vm);
</script>
</body>
</html>
6. Object.defineProperty 常用方法
6.1 功能 给对象添加属性
Object.defineProperty(对象名 , ’ 属性名 ’ , { value=’ 属性值 ’ }) , 可以给对象添加属性。
<script>
let person = {
name:"张三",
sex:"男"
}
Object.defineProperty(person,'age',{
value:"18"
})
console.log(person);
</script>
6.2 如何设置能否被枚举遍历
通过Object.defineProperty增加的属性,是不可以被枚举的,也就是不能被遍历。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
let person = {
name:"张三",
sex:"男"
}
//这里的age,设置出来是不可以枚举的,也就是不可以被遍历出来的
Object.defineProperty(person,'age',{
value:"18"
});
console.log("----------");
console.log(person);
console.log("----------");
//Object.keys(person) ,可以打印person中的键名
console.log(Object.keys(person));
console.log("----------");
//for ... in 遍历来遍历键值。
for(let v in person){
console.log(person[v]);
}
</script>
</body>
</html>
此外,ObjectdefineProperty增加的属性,在打印出来后,有些不一样,颜色会比其他直接定义的属性浅一些。
如果想要在defineProperty增加的属性里,想让他枚举的话,可以在属性值中定义enumerable为true。其中enumerable含义是,可列举的。这样设置完后,age的颜色就一样了。
//这里的设置了enumerable为true,就可以来进行遍历age了。
Object.defineProperty(person,'age',{
value:"18",
enumerable:true //这里默认值为false
});
6.3 如何定义属性值能否改变
此外,ObjectdefineProperty定义的属性值是没法改变的。
同样,将writable设置为true,就能修改属性值了。
Object.defineProperty(person,'age',{
value:"18",
enumerable:true, //设置能否枚举遍历。
writable:true, //设置能否修改属性值。
});
6.4 如何定义属性能否被删除
我们先看看,在使用ObjectdefineProperty,没有设置删除的属性下,是属性被删除的不可以的。
如何设置,这里就用到了configurable来设置。
Object.defineProperty(person,'age',{
value:"18",
enumerable:true, //设置能否枚举遍历。
writable:true, //设置能否修改属性值。
configurable:true //设置能否进行删除属性操作。
});
7. Object.defineProperty 高级方法
7.1 getter 方法 (谁获得,就调用getter方法)
7.1.1 getter 函数方法执行过程
比较高级的做法,就是使用get函数(getter)来操作
下面代码,通过number就可以控制person中的age值了,如果直接将age:number写在person中,那就实现不了number操控age的值。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
let number = 18; //通过number就可以控制person中的age值了,如果直接将age:number写在person中,那就实现不了number操控age的值。
let person = {
name:"zhangsan",
sex:"男"
}
//比较高级的做法,就是使用get函数(getter)来操作
Object.defineProperty(person,'age',{
//当有人读取perso的age属性时,get函数就会被调用,且返回值就是age的值。
get:function(){
console.log("有人读取age属性了");
return number;
}
});
console.log(person);
</script>
</body>
</html>
7.1.2 getter 函数方法的三种写法形式
见源码:
<script>
let number = 18; //通过number就可以控制person中的age值了,如果直接将age:number写在person中,那就实现不了number操控age的值。
let person = {
name:"zhangsan",
sex:"男"
}
//比较高级的做法,就是使用get函数(getter)来操作
Object.defineProperty(person,'age',{
//当有人读取perso的age属性时,get函数就会被调用,且返回值就是age的值。
// 函数的写法看下面3中:
/*
//第一种,不写名字
get:function(){
console.log("有人读取age属性了");
return number;
}*/
/*
//第二种,有名字
get:function name(){
console.log("有人读取age属性了");
return number;
}*/
//第三种,简化(正常都是简化)
get(){
console.log("有人读取age属性了");
return number;
}
});
console.log(person);
</script>
7.2 setter 函数方法 (谁设置,就调用setter方法)
setter方法和getter方法一样,就是调用时的执行条件不同,三种写法也一样。
<script>
let number = 18; //通过number就可以控制person中的age值了,如果直接将age:number写在person中,那就实现不了number操控age的值。
let person = {
name:"zhangsan",
sex:"男"
}
//比较高级的做法,就是使用get函数(getter)来操作
Object.defineProperty(person,'age',{
//当有人读取perso的age属性时,get函数就会被调用,且返回值就是age的值。
get(){
console.log("有人读取age属性了");
return number;
},
set(value){
console.log("有人修改了age属性");
number = value; //这里设置number值,为value,就可以修改number来显示age了。
}
});
console.log(person);
</script>
8. 数据代理
8.1 数据代理定义
数据代理就是通过一个对象代理对另一个对象的属性进行操作。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
let obj1 = {x:100};
let obj2 = {y:200};
//数据代理就是通过一个对象代理对另一个对象的属性进行操作。
Object.defineProperty(obj2,'x',{
get(){
return obj1.x;
},
set(value){
obj1.x = value;
console.log("修改成功")
}
})
</script>
</body>
</html>
8.2 数据代理延伸
其实我们打印一个vm对象,看到我们在data中定义的数据,是因为Object.defineProperty中的setter和getter来得到的。
vm中的data,就是存在了vm实例对象本身,但在控制台端输入vm._data,得到的结果就是这里的data属性。
<script>
Vue.config.productionTip = false;
const vm = new Vue({
// el:'#root',
//这里的data存在了vm实例对象本身,但在控制台端输入vm._data,得到的结果就是这里的data属性。
data:{
name:"清华大学",
address:"北京"
}
});
vm.$mount("#root");
console.log(vm)
;
我们可以通过这种方式来参考和解决相关问题。见下图:
所以本质上数据代理,就是通过setter和getter,修改data中的内容,进而修改了浏览器前端的内容。
对于数据代理,就是这样子的其中的Vue实例对象中的 name: 和 address: 就是通过Object.defineProperty的getter和setter,从_data中获得绑定的。
此外,注意这里的_data里的内容不是数据代理,而是数据劫持。
以上是关于Vue 注意事项 模板语法 单双向绑定 语法格式 MVVM框架 Object.defineProperty和数据代理操作的主要内容,如果未能解决你的问题,请参考以下文章