一、vue学习的基本语法
- vue2的使用要先下载vue.js文件,然后引入html页面
<script src="js/vue.js"></script>
- 如何使用vue,Vue的基本语法是什么?
- Vue可以实现在标签体和标签属性中的数值绑定。分别叫做差值语法与绑定语句
- 下面首先演示插值语法,要用到{{}}。见下:
<body>
<div id="boxOne">我是{{name}}</div>
<script>
new Vue({//首先创建一个Vue对象
el: "#boxOne",//通过el来确定数据要绑定到的容器
data:{
name: "程咬金",//这个是Vue中存储的数据,对象套对象。
}
})
</script>
</body>
3.然后我们再尝试绑定属性,就以name属性为例
在上面的div中添加name属性并绑定到Vue的值:
<div id="boxOne" v-bind:name="name">我是{{name}}</div>
v-bind也可以简写为: 你没看错就是冒号,所以上面的等价于下面
<div id="boxOne" :name="name">我是{{name}}</div>
这种绑定有个缺点就是当标签中的属性值发生改变时,Vue中的值并不会发生变化,这时候就要用到v-model,v-model专门用于input表单场景中,我们新创建一个表单测试
<form action="">
<input v-model="name">
</form>
这样当输入框中文本发生改变时,Vue中的name值也会发生改变!
二、Vue底层用到的重要函数和模型
(一)mvvm模型
mvvm模型就是model view viewmodel三个缩写,二Vue扮演的角色就是在model和view中间的viewmodel,它将底层的数据model,经过自己的处理展现到界面上,这就是viewmodel,简称vm。
(二)Object.defineproperty()
- 函数有三个参数:
Object.defineproperty("要更改属性的对象",要变化的属性,{键值对};
var people = {
name: "chenpei",
sex: "女"
}
//向对象中添加属性
Object.defineProperty(people,"age",{
value: 22,
writable: true,
//规定添加的属性值能否被修改。
enumerable: true,
//规定能否在遍历的时候被遍历到,还有其他原数据在之前提到过这里不再提
});
所以通过这种方法赋值和普通的赋值具有本质上的不同,这也是Vue底层选用的原因。
- 利用Object.defineProperty()进行的数据代理
- Object.definePeoperty()实现简单的数据代理
var people = {
name: "chenpei",
sex: "女"
}
var peopleTwo = {
name: "wuji",
sex: "男",
}
//向对象中添加属性
Object.defineProperty(people,"age",{
value: 22,
writable: true,
//规定添加的属性值能否被修改。
enumerable: true,
//规定能否在遍历的时候被遍历到,还有其他原数据在之前提到过这里不再提
});
//修改peopleTwo的getter和setter
Object.defineProperty(peopleTwo,"sex",{
//当有人从peopleTwo中读取sex属性时,会执行get方法获得people中sex属性的值
get(){
return people.sex;
},
//同上理,当有人修改sex属性时,people中的sex属性也会被setter改变
set(value){
people.sex = value;
}
});
2.Vue底层就用到了这种数据代理,请看下图(图片来源:尚硅谷)
3.这样实现数据代理之后,Vue即vm将自身_data对象中储存的数据被vm自身代理,实现数据同步,这样也方便了我们在插值语法中书写,只需要写数据名即可。
三、事件处理与事件修饰符
(一)事件绑定符:v-on:事件名="要调用的函数名" 可以简写为@事件名="要调用的函数"
(二)事件处理(Vue中方法的声明)
<div id="boxOne" v-bind:name="name">
我是{{name}}
<!--事件绑定中指定的函数会默认传入event事件对象,但是当参数中有其他参数传入,事件对象就会被覆盖,用Vue语法$符标记一下就可以不被覆盖-->
<button id="clickTest" @click="myClick($event,22)" value="点击事件"></button>
</div>
<script>
new Vue({//首先创建一个Vue对象
el: "#boxOne",//通过el来确定数据要绑定到的容器
data:{
name: "程咬金",//这个是Vue中存储的数据,对象套对象。
},
methods:{
myClick(event,num){
//在控制台输出测试
console.log(event,num);
}
}
})
</script>
控制台输出内容:
(三)事件处理修饰符之取消冒泡修饰符
- 我们对上面例子再增加内容,如下了解下冒泡事件触发
<div id="boxOne" v-bind:name="name" @click="myClickDiv">
我是{{name}}
<!--事件绑定中指定的函数会默认传入event事件对象,但是当参数中有其他参数传入,事件对象就会被覆盖,用Vue语法$符标记一下就可以不被覆盖-->
<button id="clickTest" @click="myClick($event,22)" value="点击事件"></button>
</div>
<script>
new Vue({//首先创建一个Vue对象
el: "#boxOne",//通过el来确定数据要绑定到的容器
data:{
name: "程咬金",//这个是Vue中存储的数据,对象套对象。
},
methods:{
myClick(event,num){
//在控制台输出测试
console.log(event,num);
//看看事件的触发者
console.log("内部button的触发者是:" + event.target);
},
//div的点击事件函数
myClickDiv(event){
console.log(event,"我是div中的点击事件函数");
console.log("div中事件的触发者是:" + event.target);
}
}
})
</script>
控制台内容如下:
由以上内容我们可以知道:
- 所谓冒泡,就是事件自里向外触发
- 触发者都是最里面的元素
- 原始方式取消冒泡,在上文中最内部方法坐如下修改
myClick(event,num){
//取消冒泡
event.stopPropagation();
//在控制台输出测试
console.log(event,num);
//看看事件的触发者
console.log("内部button的触发者是:" + event.target);
}
然后当我们点击按钮的时候就只有最里面的函数得到执行。
- 用Vue的事件修饰符的方式,只需要在函数绑定的时候加上.修饰符即可
<button id="clickTest" @click.stop="myClick($event,22)">
也能阻止冒泡
(三)其他的事件处理修饰符
- 都有哪些事件修饰符:
prevent | 阻止元素默认事件,像a标签的跳转等等 |
stop | 阻止冒泡 |
once | 事件仅允许触发一次 |
capture | 使用事件的捕获模式,就是由外到内执行函数 |
self | 只有Event.target是自己的时候才执行函数,如果在例子中加入此,也可阻止冒泡 |
passive | 事件的默认函数立即执行,无需等待回调函数执行完毕 |
- passive解释:
- 有些事件是先执行回调后执行默认事件的,比如说wheel(滚轮滚动)
<style>
#textSmall{
width: 100px;
height: 40px;
background-color: aquamarine;
overflow: auto; /*设置溢出显示滚动条*/
}
</style>
<body>
<div id="textSmall" @wheel="whenWheel">
Vue (读音 /vjuː/,类似于 view) 是一套用于构建用户界面的渐进式框架。
与其它大型框架不同的是,Vue 被设计为可以自底向上逐层应用。
Vue 的核心库只关注视图层,不仅易于上手,还便于与第三方库或既有项目整合。
另一方面,当与现代化的工具链以及各种支持类库结合使用时,
Vue 也完全能够为复杂的单页应用提供驱动。
</div>
<script>
new Vue({
el: "#textSmall",
methods:{
whenWheel(){
//制造函数执行长时间,看看默认行为执行情况
for(i = 0; i<10000;i++){
console.log("我行");
}
}
}
})
</script>
</body>
结果是每当我在内容上面通过鼠标滚轮滚动时,要等一万个我行输出完毕,滚动条才会移动内容才会变化。
2.要取消这种行为,只需要修饰符passive
<div id="textSmall" @wheel.passive="whenWheel">
四、按键别名与键盘事件
(一)什么是按键别名?
当我们绑定键盘事件的时候,事件对象会自动获取你所按的按键的别名和键码保存在属性中
下面例子用input元素的keyup事件来在控制台获取按键别名,利用event.key属性
<form action="" id="formContainer">
<input type="text" placeholder="输入完内容后点击回车!" @keyup="keyMethod">
</form>
<script>
new Vue({
el: "#formContainer",
methods:{
keyMethod(ev){
console.log("您按的键是:" + ev.key);
}
}
})
</script>
再给按键事件指定特定的键触发,需要加上if判断语句
if(ev.keyCode == 13)//十三是回车键的键码
console.log("您按的键是:" + ev.key);
}
(二)Vue键盘别名绑定事件快捷方式
- 格式:
@keyup.键盘别名 ="要绑定的函数";
- 常见的键盘别名:enter(回车)、delete(删除键和退格键)、esc(退出)、tab(换行)、 up\down\right\left(上下左右)
- 要注意有些键已经绑定了浏览器事件,要注意,比如tab点下去就会转移元素焦点,所以该键只能配合keydown使用。还有alt control shift 和徽标键,属于修饰键,如果用keyup的话只有control键不动按住其他键松开才会生效,要想单独使用就要用keydown了。
@keyup.ctrl.y = "函数" 按住ctrl和y,y起才能执行函数
- 还要注意,有些键盘别名是驼峰命名,要想用.的方式,命名要改为纯小写中间用-隔开 ,举例如下
@keyup.caps-lock ="函数"
修饰符可以连着写
五、Vue属性与计算属性
(一)属性
- Vue中的属性是在data中定义的:
- 那么我们利用属性来实现个效果,两个输入框,一个span,当输入框内容发生改变时,span中内容也要发生改变。
<form action="" id="formContainer">
<input type="text" v-model="firstName"><br><br>
<input type="text" v-model="lastName"><br><br>
<!--直接动态绑定input输入框的值到Vue的属性,实现span内容自动更新-->
<span>{{firstName}}-{{lastName}}</span>
</form>
<script>
var vm = new Vue({
el: "#formContainer",
data:{
firstName: "陈",
lastName: "湫"
},
methods:{
keyMethod(ev){
console.log("您按的键是:" + ev.key);
}
}
});
</script>
(二)Vue的计算属性
- 像上面span中的内容是有Vue中的两个属性计算出来的就可以指定为一个计算属性,以满足Vue在html界面上的简洁化。
- Vue计算属性的声明:
<form action="" id="formContainer">
<input type="text" v-model="firstName"><br><br>
<input type="text" v-model="lastName"><br><br>
<!--直接动态绑定input输入框的值到Vue的属性,实现span内容自动更新-->
<span>{{fullName}}</span>
</form>
<script>
var vm = new Vue({
el: "#formContainer",
data:{
firstName: "陈",
lastName: "湫"
},
methods:{
keyMethod(ev){
console.log("您按的键是:" + ev.key);
}
},
computed:{
fullName:{
//当有调用fullName时,会自动执行getter和setter,来给fullName属性赋值
get(){
//这里的this被Vue优化为了vm对象
return this.firstName + "-" + this.lastName;
}
}
}
});
</script>
最终效果和上面一致。
- 再加上set,来实现,当页面加载完成后,更改fullname的值后,Vue中的相关属性也发生改变
set(value){
var zu = value.split("-");//将值以-为间隔拆分成数组
this.firstName = zu[0];
this.lastName = zu[1];
}
实现效果,我更改fullname的值,自动调用setter
属性值也跟着变化:
- 这种方式跟插值的方式比有什么优点呢?
- 页面更加清晰。
- 计算属性有缓存,当fullName被多次调用时,get方法只用执行一次,只有当fullName相关联的属性值发生变化时,才会再次执行;而插值语法动态绑定不一样,只要是Vue中的属性变化,都要重新再读取属性值。
(三)Vue中计算属性的简写
- 使用简写的前提条件是:确定计算属性只需要计算并展示,并不会被修改(即没有setter)的情况下,才可以使用。
- 据此上面的fullName计算属性可以直接改写为:相当于getter了
fullName(){
return this.firstName + "-" + this.lastName;
}
六、监视属性
(一)什么是监视属性?
- 它能够监视Vue中的属性值和计算属性值,当他们发生变化时,执行一些自定义的逻辑
- 语法,以监视上面例子的fullName为例:
watch:{
fullName:{
handler(newValue,oldValue){
console.log("属性发生了改变变化前的值是:" + oldValue );
}
}
}
然后我们修改在页面控制台修改fullName的值,发现watch的handler执行了
(二)监视属性案例练习
<div id="weatherTest">
<span>我爱着{{rel}}!</span><br>
<button @click="changeWeather">点我改变天气</button>
</div>
<script>
new Vue({
el: "#weatherTest",
data: {
season: "冬天"
},
computed: {
rel(){
if(this.season == "冬天"){
return "北风吹雪";
}else if(this.season == "春天"){
return "鸟语花香"
}
}
},
methods:{
changeWeather(){
if(this.season == "冬天"){
this.season = "春天";
}else{
this.season = "冬天";
}
}
},
watch:{
season:{
//immediate: true, //在值发生变化之前先执行一次函数
handler(newValue,oldValue){
console.log("值发生了改变,改变前是:" + oldValue + "\n改变后的值是:" + newValue);
}
}
}
})
</script>
效果是当季节发生变化,我爱的天气发生变化,同时season属性被监控,改变前后的值被输出到控制台
- 另一种监视写法:
vm.$watch(要监视的变量,{handler函数和一系列原数据对});
(三)深度属性监视
- 当属性里面有对象(即层级结构时,需要用到深度属性监视),看下面例子。
当number中a的值发生改变的时候,控制台输出它的上一个值,而b值的变化不会影响到handler函数:
<div id="deepSeeContainer">
<span>a的值是:{{number.a}}</span><br>
<button @click="number.a++">点我给a的值加1</button><br>
<span>b的值是:{{number.b}}</span><br>
<button @click="number.b++">点我给a的值加1</button>
</div>
<script>
new Vue({
el: "#deepSeeContainer",
data:{
number:{
a: 1,
b: 2
}
},
watch:{
"number.a":{
//注意监视层级结构的语法,加引号是因为键本来就只能是字符串,不过我们习惯直接写了,这里却不允许去掉引号
handler(newValue,oldValue){
console.log("a的值发生了改变,原来的值是:" + oldValue)
}
}
}
});
</script>
- 那么如何实现number中只要有值改变就触发函数呢?修改一下代码,仅展示watch部分:
watch:{
number:{
deep: true, //不开启这个参数,Vue的watch就无法看到直接属性内的数据
//因为选的是上层结构,所以这里传入的参数发生了改变,是一个对象,里面分别有a和b的新值
handler(old){
console.log("a或b的值发生了改变,原来的值是:" + "a的新值是" +old.a +"b的新值是:" + old.b);
}
}
}
这样两者的变化都能触发handler函数了
七、Vue中使用函数时的this指代
- 当Vue中是Vue中规定的要写函数的地方,我们用普通的函数声明方法,当中的this指代的是Vue实例vm。仅举例子:
- 当Vue需要用setTimeout这种js原生函数时,用传统的函数声明(或调用)方法,那么里面的this就是windows对象,要是用箭头函数this就指代的是vm对象。
- 原因,当用箭头函数声明时,this指的是拥有者,普通方式是函数的调用者。
- 所以由以上总结出最佳实践,当是vue规定的函数时,用普通声明方式,当用到原生函数时且涉及到Vue中属性的this调用,要用箭头函数声明。
八、class样式绑定和style属性的绑定(上面学习内容的综合练习)
(一)class样式绑定练习
- 首先我们要明确一点:
- 下面这种情况div是可以同时使用上面三种样式的:
-
<style> .one{ } .two{ } .three{ } </style> <div class="one two three"></div>
- 用数组方式实现div三种样式的随机切换:
<style>
.one{/*div的基础样式*/
border:2px solid green;
border-radius: 3px;
width: 200px;
height: 200px;
}
.two{
background-color:aquamarine;
}
.three{
background-color:brown;
}
.four{
background-color:aliceblue;
}
</style>
<body>
</div>
<div id="classShuan" class="one" :class="colorChoose" @click="changeColor"></div>
<script>
new Vue({
el:"#classShuan",
data:{
colorChoose: "two",
//这个属性我们利用函数把它的值随机化
//而它又被上面的class属性绑定到,所以class选择也是随机的
},
methods:{
changeColor(){
var colorArr = ["two","three","four"];
//生成一个0到3的随机整数,不包括3,把数组下标随机化
var downIndex = Math.floor(Math.random()*3);
//修改colorChoose的值
this.colorChoose = colorArr[downIndex];
//最后要把该函数绑定到div点击事件上,实现点击随机切换三种效果
}
}
})
</script>
</body>
测验通过!
- 用数组的方式动态让用户改变样式,用对象的方式
<style>
.one{/*div的基础样式*/
border:2px solid green;
border-radius: 3px;
width: 200px;
height: 200px;
}
/* 让按钮在div元素的下方居中不动 */
#classShuan div{
margin: 140px auto auto auto;
text-align: center;
}
.five{
text-shadow: 3px 3px 5px red;
/*添加文字阴影效果*/
}
.six{
text-align: center;
}
</style>
<body>
<div id="classShuan" class="one" :class="colorChoose">
<span>我是神仙不下凡</span>
<div>
<button @click="addTextShadow">点我增加文本阴影</button>
<button @click="addTextCenter">点我让文字居中</button>
</div>
</div>
<script>
new Vue({
el:"#classShuan",
data:{
colorChoose:{
"five": false,
"six": false
//这时候我们动态绑定到class的是一个对象,
//这个对象的键就是我们要动态添加的class,只有为true时才会生效
},
},
methods:{
addTextShadow(){
this.colorChoose.five = true;//增加文字阴影的函数,绑定到按钮上
},
addTextCenter(){
this.colorChoose.six = true;//增加文字居中的函数,绑定到按钮上
}
}
})
</script>
</body>
点击第一个按钮效果:
再点击第二个按钮增加居中效果:
(二)style属性样式动态绑定
- 需要用到样式对象,要声明在Vue中
- 例子,放大文本的字体到45px;
- 原来的写法:
<div style="font-size:45px;"></div>
2 .Vue动态绑定的写法
<body>
<span :style="myStyleObj">我是神仙不下凡</span>
<script>
new Vue({
el:"#classShuan",
data:{
myStyleObj:{
fontSize: "48px",
//这是样式对象内部,键值就是要修改的样式属性名
//跟原来不一样的是要改成驼峰命名法
}
},
});
</script>
</body>
两种方式效果一致:
九、v-if和v-show的简单使用
(一)两者的异同之处
- 相同之处
- 可以单独使用,不用跟标签属性绑定。
- 都只能是布尔值,可以在Vue中读取值。
- 如果为false都能做到让元素消失
- 不同之处
- v-show值为false时,实际上是改变了元素的display属性值为none,但是元素节点还在。
- v-if值为false时,就是直接把元素节点删除了
(二)v-if的整体使用
- 简单的例子,改变v-if的值来控制元素的出现与消失。直接利用上面例子,仅需要注意v-if和a的绑定值即可
<div id="classShuan" class="one" :class="colorChoose" v-if="a">
<span :style="myStyleObj">我是神仙不下凡</span>
<div>
<button @click="addTextShadow">点我增加文本阴影</button>
<button @click="addTextCenter">点我让文字居中</button>
</div>
</div>
<script>
var vmMe = new Vue({
el:"#classShuan",
data:{
colorChoose:{
"five": false,
"six": false
//这时候我们动态绑定到class的是一个对象,
//这个对象的键就是我们要动态添加的class,只有为true时才会生效
},
myStyleObj:{
fontSize: "48px",
//这是样式对象内部,键值就是要修改的样式属性名
//跟原来不一样的是要改成驼峰命名法
},
a: true
},
</script>
我们在控制台模仿用户改变a的值让元素消失:
- v-if可以和v-else-if以及v-else一起使用实现多级判断。
<div id="ifTest">
<div v-if="a == 1">第一个</div>
<div v-else-if="a == 2">第二个</div>
<div v-else>最后一个</div>
</div>
<script>
var vmIf = new Vue({
el: "#ifTest",
data:{
a: 0,//默认设置为零
}
})
</script>
因为默认a为0,前面几个条件都不满足,所以v-else生效:
然后我们模仿用户修改a的值
- 使用上面的配套if这几个div中间不能被其他没带v-if的元素打断,否则就会报错
- 当使用标准的v-if,v-else-if,那么当有一个条件满足,其他的都直接略过为false。
十、列表渲染(v-for的使用)
(一)使用前置信息
- v-for的形式:
<ul>
<li v-for="(value,key) in 要遍历的对象或数组" :key="key">
{{value.对应的键名}}
</li>
</ul>
- 这样书写后,在加载界面的时候,v-for就会帮我们遍历在Vue中对应的对象,并且增加对应数量的li
- 在遍历时会从对象或数组中获取两个内容,一个是对应的值,另一个是键或者下标
- :key需要动态绑定一个值,保证每个li的唯一性,这里用的是数组下标。
- 插值语法中的变量也可以来自v-for中的形参。
(二)案例演示
- 遍历一个数组,数组中储存的是对象,那么遍历拿到的就是对象
<ul id="ulTest" >
<li v-for="(obj,key) in peoples" :key="key">
{{obj.name}}-{{obj.age}}-love:{{obj.love}}
</li>
</ul>
<script>
new Vue({
el: "#ulTest",
data:{
peoples:[
{name:"路飞",age: 23,love:"雏田"},
{name:"鸣人",age: 19, love:"娜美"},
{name:"萧炎",age: 22, love:"美杜莎"}
]
}
})
</script>
效果:
(三)案例使用的key绑定为数组下标的隐患
一、Vue的虚拟dom对比算法,那我们修改上面的例子为例,仅展示增加部分
<button @click="addPeople">点我添加新人</button>
---------------------------
methods:{
addPeople(){
var wang = {name:"老王",age: 22,love: "云韵"};
//将新人推入数组,注意从前面进入
this.peoples.unshift(wang);
}
}
- 这里我们增加了一个按钮,实现点击增加新人。那么在这个过程中虚拟dom是如何实现对比算法的呢?
- 页面加载时的虚拟dom中有三个对象,分别是路飞、鸣人、萧炎,然后我们点击按钮,数组中的数据发生变化了,就会触发虚拟dom的对比算法,对比算法根据key值确定对比双方
这样还会连累无辜,导致出错,例如每个li中都加了一个输入框
<li v-for="(obj,key) in peoples" :key="key">
{{obj.name}}-{{obj.age}}-love:{{obj.love}}
<input>
</li>
加载完页面后,我们在输入框输入各自对应的数据,
然后点击添加新人错误出现:input内容全乱了!
原因:
- 解决方法,
- 将数据从后面插入。
- 将key值指定为每个对象中的唯一值,这样key的对应对象就固定了,那么diff算法对比的对象就都一样了。
十一、列表过滤
(一)用监听属性来实现
<div id="filterTest">
<h1>列表搜索</h1>
<!-- v-model绑定到Vue,让Vue监测到变化-->
<input type="text" placeholder="请输入要搜索的关键字" v-model="inContent">
<ul>
<li v-for="value in needPeoples" :key="value.id">
{{value.name}}--{{value.age}}--love:{{value.love}}
</li>
</ul>
</div>
<script>
new Vue({
el: "#filterTest",
data:{
inContent:"" ,//默认为空串
peoples:[//数据源
{id:"001",name:"路飞",age: 23,love:"雏田"},
{id:"002",name:"鸣人",age: 19, love:"娜美"},
{id:"003",name:"萧炎",age: 22, love:"美杜莎"},
{id:"004",name:"老王",age: 22,love: "云韵"}
],
needPeoples:[]
},
watch:{
inContent:{
immediate: true,
//让函数开始就执行一次,即看是否包含空字符,肯定包含全部展示
//创建数组处理后返回
handler(val){
var shuzu = [];
//查看数据中的值是不是包含输入框中的值
this.needPeoples = this.peoples.filter((p)=>{
return p.name.includes(val);
})
}
}
}
})
</script>
(二)用计算属性实现
<div id="filterTest">
<h1>列表搜索</h1>
<!-- v-model绑定到Vue,让Vue监测到变化-->
<input type="text" placeholder="请输入要搜索的关键字" v-model="inContent">
<ul>
<li v-for="value in needPeoples" :key="value.id">
{{value.name}}--{{value.age}}--love:{{value.love}}
</li>
</ul>
</div>
<script>
new Vue({
el: "#filterTest",
data:{
inContent:"" ,//默认为空串
peoples:[//数据源
{id:"001",name:"路飞",age: 23,love:"雏田"},
{id:"002",name:"鸣人",age: 19, love:"娜美"},
{id:"003",name:"萧炎",age: 22, love:"美杜莎"},
{id:"004",name:"老王",age: 22,love: "云韵"}
],
},
computed:{
needPeoples:{
get(){
return this.peoples.filter((p)=>{
return p.name.includes(this.inContent);
})
}
}
}
})
</script>
(三)在给表格添加根据年龄排序的功能
<div id="filterTest">
<h1>列表搜索</h1>
<!-- v-model绑定到Vue,让Vue监测到变化-->
<input type="text" placeholder="请输入要搜索的关键字" v-model="inContent">
<button @click="sortType = 1" >年龄正序</button>
<button @click="sortType = 2">年龄逆序</button>
<button @click="sortType = 0">原顺序</button>
<ul>
<li v-for="value in needPeoples" :key="value.id">
{{value.name}}--{{value.age}}--love:{{value.love}}
</li>
</ul>
</div>
<script>
new Vue({
el: "#filterTest",
data:{
sortType: 0,
inContent:"" ,//默认为空串
peoples:[//数据源
{id:"001",name:"路飞",age: 23,love:"雏田"},
{id:"002",name:"路阳",age: 34,love:"雏田"},
{id:"003",name:"花路",age: 12,love:"雏田"},
{id:"004",name:"鸣炮",age: 23,love:"雏田"},
{id:"005",name:"鸣人",age: 19, love:"娜美"},
{id:"006",name:"萧炎",age: 22, love:"美杜莎"},
{id:"007",name:"老王",age: 13,love: "云韵"}
],
},
computed:{
needPeoples:{
//每当计算变量依赖的Vue变量发生变化,getter都会再次执行
get(){
//先用变量承接,以后排序在此基础上进行,保证在搜索中的数据排序
const arrMe = this.peoples.filter((p)=>{
return p.name.includes(this.inContent);
});
//在这里判断排序的类型0为正常顺序,1为正序,2为逆序
//判断,默认为0即为false,不会执行排序,即原顺序
if(this.sortType){
arrMe.sort((a,b)=>{
return (this.sortType == 1)? b.age - a.age:a.age - b.age;
})
}
//记得返回
return arrMe;
}
}
}
})
</script>
十一、Vue如何实现对自身实例中属性的监控?
(一)重温Vue中的数据
- Vue中的数据都在data中,分为数组和对象两种类型。在其中声明的数据会受到Vue实例vm的管理
- 那么如何管理?
- 就对象而言,当vm创建完成之后,Vue中data中的对象以及对象中的每个键都会被增加getter和setter方法,放在vm._data这个属性中,同时数据代理到了vm.一级属性名中.
- 如下
<!-- Vue数据监测测试,作如下结构-->
<div id="seeText">
<ul>
<li>{{people.name}}--{{people.age}}</li>
</ul>
</div>
</body>
<script>
var vm =new Vue({
el:"#seeText",
data:{
people:{
name:"路飞",
age: 34
}
}
})
3.上面的数据在生成页面之后people对象中间的数据都交给了vm实例管理,对象中的各个属性也都被数据劫持,增加了对应的getter和setter,以实现响应式(响应式就是当people中的数据改变时就会调用setter,setter中会引起整个模版用到该属性的位置重新加载。所以对象的属性拥有setter和getter很重要,这也是属性被Vue实例监测的重要条件。
- 就数组而言,如下,
<!-- Vue数据监测测试,作如下结构-->
<div id="seeText">
<ul>
<li>{{people[0]}}--{{people[1]}}</li>
</ul>
</div>
</body>
<script>
var vm =new Vue({
el:"#seeText",
data:{
people:["路飞",34]
}
})
</script>
- 数组在Vm中数据没有对应的getter,setter来监控数据的变化,但是Vue是采用将数组中原生的对原数组有影响的方法做了强化,当页面生成后,被Vue管理的数组调用的像push、pop,shift,unshift等等方法,都被强化过,调用修改后还是会被监测,并及时响应到页面。
(二)那如何在vm形成后(即页面完成后)再添加属性到Vue中,且实现响应式?
一、错误的写法,还以上例为例。
- 对象数据已经确定,我们想要再添加love属性到Vue中且会被自动解析到页面上。
<!-- Vue数据监测测试,作如下结构-->
<div id="seeText">
<ul>
<li>{{people.name}}--{{people.age}}--{{people.love}}</li>
</ul>
</div>
</body>
<script>
var vm =new Vue({
el:"#seeText",
data:{
people:{name:"路飞",age:34}
}
})
</script>
加载完页面如下:
我们模仿用户在vm中添加love属性。
添加完后,love的数据并没有被解析,这说明数据虽然添加了,但是Vue并没有发现属性值的增加,而新添加的属性也绝没有setter和getter。
- 数组对象已确定,要在页面加载完成后,向数组添加新值和修改元素值,并且要求被响应
<body>
<!-- Vue数据监测测试,作如下结构-->
<div id="seeText">
<ul>
<li>{{people[0]}}--{{people[1]}}--{{people[2]}}</li>
</ul>
</div>
</body>
<script>
var vm =new Vue({
el:"#seeText",
data:{
people:["路飞",34]
}
})
</script>
二、根据上面知识给出正确方法:
- 数组
应使用语句:
修改值,使用splice函数
vm._data.people.splice(0,1,"鸣人");
增加值,使用push();
可见都修改成功
- 对象
应使用语句
格式:
Vue.set(要添加属性的对象,要添加或修改的属性,属性值);
或者
vm.$set((要添加属性的对象,要添加或修改的属性,属性值);
具体:
vm.$set(vm._data.people,"love","雏田");
Vue.set(vm._data.people,"love","雏田");
十二、利用v-model进行的表单数据同步及细节
- 首先创建一个具有各种类型的表单
<!-- 阻止默认行为 -->
<form id="formGet" @submit.prevent="printInfo">
账号:<input type="text" v-model="custer"><br>
密码:<input type="password" v-model="pass"><br>
性别:<!--因为v-model自动同步的是value值,而单选框没有输入所以要指定-->
男<input type="radio" v-model="sex" name="sex" value="male">
女<input type="radio" v-model="sex" name="sex" value="female"><br>
兴趣:
打篮球<input type="checkbox" v-model="inster" value="basketball">
跳舞<input type="checkbox" v-model="inster" value="dance">
下棋<input type="checkbox" v-model="inster" value="chess"><br>
选择城市:
<select v-model="city">
<option value="shanghai">上海</option>
<option value="beijing">北京</option>
<option value="shenzhen">深圳</option>
<option value="zhengzhou">郑州</option>
</select><br>
其他信息:
<textarea v-model="it"></textarea><br>
<input type="checkbox" v-model="agree">是否同意协议<a>某某协议</a><br>
提交信息:<input type="submit">
</form>
<script>
new Vue({
el: "#formGet",
data:{
custer:"",
pass: "",
sex: "",
inster: [],//这里注意因为多选框,所以要用数组接收,可能的多个值。
city: "",
it: "",
agree: ""
},
methods:{
printInfo(){
//将收集到的信息打印到控制台,虽然_data有getter和setter但是转换成json的只有数据。
console.log(JSON.stringify(this._data));
}
}
})
</script>
效果:
- 单选框和多选框要注意的点:
- v-model要用数组接收,同时每个多选框都要指定value的值
- 当多选框只有一个时,就会统计是否选中,值为布尔值
- 当单选框没指定value时,则默认收集的是checked的内容(布尔值),即是否被选中。
- 如何用修饰符限制v-model收集的model类型,如下
<input type="number" v-model.number="age">
这样的话收集到的数据都会转化为数值
- v-model的其他修饰符:
- v-model.trim 去掉前后的空格
- v-model.lazy v-model的数据同步要等到元素失去焦点再执行 m