目录
0x00 Vue的特点
1.组件化:可以将页面中可复用的元素甚至整个页面都可以看做组件,写页面的过程,就是写组件,然后页面是由这些组件拼接起来的组件
2.数据驱动:就是让我们只关注数据层,只要数据变化,页面(即视图层)会自定更新(双向数据绑定 MVVM)至于如何操作DOM,完全交给Vue去完成,咱们只需要关注数据,数据变了,页面自动同步变化了,很方便。
0x01关于MVC MVP MVVM
都是为了解决图形界面应用程序复杂性管理问题而产生的一种架构模式
演变:MVC >> MVP >> MVVM
1.MVC:
view: 是提供给用户的操作界面,是一个空壳 shell
model: 是程序需要操作的数据和信息
controller: 接收 view层传递过来的指令,选取model层对应的数据,进行相应的操作
mvc 是单向数据绑定,即model绑定到view
注意:前端说的MVC 和后端说的MVC 不同,后端说的MVC更接近于前端说的MVP
2.MVP:
0x01 引包,留坑,实例化,实例化,插值表达式
1.引包:
确认已经下载了node,官网:https://nodejs.org/en/download/
然后创建 你要做的项目的文件夹。在命令行中cd到项目文件夹。
然后执行命令npm install vue(如需下载自己要的版本在vue后面加上@版本号),将vue包下载到你的项目文件夹中,然后从包中找到vue.js文件,移动到index.html同级目录下。
在index.hmtl页面引入刚下载的包
<script type="text/javascript" src="vue.js"></script>
2.留坑:
即留一个vue模板插入的地方或者是vue代码对其生效的地方。
例如留一个div,然后给div一个id或者一个class名。
3.实例化 即启动vue
启动:new Vue({el:目的地,template:模板内容});实例化传入的参数是一个对象options
options:
- 挂载目标 el:对应上面留坑的坑位,即提供一个在页面已经存在的DOM元素作为Vue实例的挂载目标。挂载目标中就可以使用vue的语法来进行操作。可以通过vm.$el来访问挂载目标。
var vm = new Vue({ el:'#app', data:{ username:'' } }) console.log(vm.$el);
- 内容 template:将会自动替换坑位的代码
- 数据 data:vue实例的数据对象,必须是纯粹的对象。也可以用函数的形式返回一个对象。同理,可以用vm.$data来访问原始的数据对象,同时vue实例也代理了data对象上所有的属性,因此访问vm.a 等价于访问vm.$data.a
-
<script> var vm = new Vue({ el:'#app', data:{ username:'DataBank123' } }) console.log(vm.$el); console.log(vm.$data.username); </script>
4.插值表达式{{}}
数据绑定最常见的形式就是使用插值表达式
插值表达式内填入data里面的属性名 即可取到属性的值{{data里面的属性名}}
{{}}:不会解析html标签,效果同v-text
v-text :不会解析html标签,数据双向绑定
v-html:会解析html标签,数据双向绑定
v-once指令:数据初始化后不可修改
证明:
<div id="app">
<input type="text" class='form-control' v-model='username'>
{{username}}
<p v-text='username'></p>
<p v-html="username"></p>
<p v-once>{{username}}</p>
</div>
<script>
var vm = new Vue({
el:'#app',
data:{
username:'<h1>DataBank123</h1>'
}
})
</script>
效果:
{{}}表达式 中可以进行运算,但是不能用++这种,因为vue是双向数据绑定,会进入死循环
证明:
<div id="app">
{{count+1}}
</div>
<script>
var vm = new Vue({
el:'#app',
data:{
username:'<h1>DataBank123</h1>',
count:1
}
})
</script>
效果:
<div id="app">
{{count+1}}
{{username.toUpperCase()}}
{{username.toLowerCase()}}
{{status?"login":"logout"}}
</div>
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<!-- 2.留坑 -->
<div id='app'></div>
<!-- 1.引包 -->
<script type="text/javascript" src="vue.js"></script>
<!-- 3.实例化 -->
<script type="text/javascript">
new Vue({
el:'#app',
template:"<div>我这里是模板内容{{msg}}</div>",
data:function(){
return {
msg:'Hello Vue'
}
}
})
</script>
</body>
</html>
坑!:
1.tamplate里面只能有一个根标签
0x01 常用指令
指令:vue语法中 v-开头的html属性
v-text:给元素的innerText赋值必须是双标签
v-html: 给元素的innerHTML赋值
复习:innerHMTL中标签会被解析,innerText中不论什么标签都被当成字符串文本。
v-bind: 插值表达式不能用在html属性上,这种情况应该用v-bind
<body>
<div class="container">
<div class="page-header">
<div class="page-title">
<h1>Vue实验室</h1>
</div>
</div>
<div id="app">
<ul class="nav nav-pills">
<li role="presentation" v-bind:class="isActive"><a href="#">Home</a></li>
<li role="presentation"><a href="#">Profile</a></li>
<li role="presentation"><a href="#">Messages</a></li>
</ul>
</div>
</div>
</body>
<script>
var vm = new Vue({
el:'#app',
data:{
isActive:"active"
}
})
</script>
动态参数:
html属性名和属性值都可以是动态的:
<a v-bind:[attrName]="url">Click</a>
data:{
attrname:"href",
url:"http://101.200.142.148:90/"
}
注意虽然view层attrName N是大写,但是vue会将其转为小写,所以vm层必须是小写。
v-bind: 可以缩写为 :,即直接写一个冒号
<body>
<div class="container">
<div class="page-header">
<div class="page-title">
<h1>Vue实验室</h1>
</div>
</div>
<div id="app">
<a v-bind:[attrKey]="value">Click</a>
</div>
</div>
</body>
<script>
var vm = new Vue({
el:'#app',
data:{
attrkey:'href',
value:'http://101.200.142.148:90/'
}
})
</script>
表达式结果的类型除了字符串之外,还可以是对象或者数组
<p :class="{active:isActive}">hello DataBank</p>
data:{
isActive:false
}
当isActive为true的时候,class被赋值为active
<body>
<div class="container">
<div class="page-header">
<div class="page-title">
<h1>Vue实验室</h1>
</div>
</div>
<div id="app">
<a :class="[activeClass,errorClass]">Click</a>
</div>
</div>
</body>
<script>
var vm = new Vue({
el:'#app',
data:{
key:'href',
value:'http://101.200.142.148:90/',
activeClass:"active",
errorClass:"error"
}
})
</script>
效果:
style属性的绑定:
写法一:
<body>
<div class="container">
<div class="page-header">
<div class="page-title">
<h1>Vue实验室</h1>
</div>
</div>
<div id="app">
<a :style="styleObj">Click</a>
</div>
</div>
</body>
<script>
var vm = new Vue({
el:'#app',
data:{
styleObj:{color:'red',fontSize:'12px'}
}
})
</script>
写法二:
<body>
<div class="container">
<div class="page-header">
<div class="page-title">
<h1>Vue实验室</h1>
</div>
</div>
<div id="app">
<a :style="[colorStyle,fontStyle]">Click</a>
</div>
</div>
</body>
<script>
var vm = new Vue({
el:'#app',
data:{
colorStyle:{color:'red'},
fontStyle:{fontSize:"12px"}
}
})
</script>
v-if: 用于条件性地渲染一块内容,当值为true的时候,将所在标签append到dom树,值为false的时候,不将所在标签append
<body>
<div class="container">
<div class="page-header">
<div class="page-title">
<h1>VueLab</h1>
</div>
</div>
<div id="app">
<!-- .prevent修饰符用来阻止表单跳转 -->
<form action="" @submit.prevent='login'>
<h1 v-if='status'>Hello DataBank</h1>
<h1 v-if="username=='lampol'">Lampol</h1>
</form>
</div>
</div>
</body>
<script>
var vm = new Vue({
el:'#app',
data:{
status:true,
username:'shang'
}
})
</script>
v-else-if:同上
v-else:如果之前的v-if和v-else-if的值都是false,则将所在标签append到dom树对应的位置
<body>
<div class="container">
<div class="page-header">
<div class="page-title">
<h1>VueLab</h1>
</div>
</div>
<div id="app">
<!-- .prevent修饰符用来阻止表单跳转 -->
<form action="" @submit.prevent='login'>
<p v-if='score<60'>不及格</p>
<p v-else-if='score>=60 && score<80'>良好</p>
<p v-else-if="score>=80 && score<=100">优秀</p>
<p v-else>搞错了吧,阿sir</p>
</form>
</div>
</div>
</body>
<script>
var vm = new Vue({
el:'#app',
data:{
score:88
}
})
</script>
v-show :条件渲染,值为true时显示标签,值为false时隐藏标签,即给标签加上display:none属性。
<body>
<div class="container">
<div class="page-header">
<div class="page-title">
<h1>VueLab</h1>
</div>
</div>
<div id="app">
<!-- .prevent修饰符用来阻止表单跳转 -->
<form action="" @submit.prevent='login'>
<h1 v-show='isShow'>Hello DataBank</h1>
</form>
</div>
</div>
</body>
<script>
var vm = new Vue({
el:'#app',
data:{
isShow:false
}
})
</script>
v-for:列表渲染,需要使用 item in/of items 形式的特殊语法,其中items是源数据数组,而item则是被迭代的数组元素的别名
可以循环数组 和对象。
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<!-- 2.留坑 -->
<div id='app'></div>
<!-- 1.引包 -->
<script type="text/javascript" src="vue.js"></script>
<!-- 3.实例化 -->
<script type="text/javascript">
new Vue({
el:'#app',
template:`
<div>
<div v-text='mytext'></div>
<div v-html='myHtml'></div>
<button v-if='checkvif'>测试v-if</button>
<button v-if='num==1'>num==1 is true</button>
<button v-else-if='num==2'>num==2 is true</button>
<button v-else>其他情况</button>
<div v-show='isDisplay'>我是v-show</div>
<ul>
<li v-for="v in arrayfor">{{v}}</li>
</ul>
<ul>
<li v-for="(v,k) in arrayfor">key:{{k}} value:{{v}}</li>
</ul>
<ul>
<li v-for="v in objectfor">value:{{v}}</li>
</ul>
<ul>
<li v-for="(v,k) in objectfor">key:{{k}} value:{{v}}</li>
</ul>
</div>
`,
data:function(){
return {
mytext:'我替换template中的mytext',
myHtml:'<h1>myHtml的值</h1>',
checkvif:true,
num:3,
isDisplay:false,
arrayfor:['html','python','css','js',],
objectfor:{name:'xiaoming',age:'17',school:'xdu'}
}
}
})
</script>
</body>
</html>
<body>
<div class="container">
<div class="page-header">
<div class="page-title">
<h1>VueLab</h1>
</div>
</div>
<div id="app">
<ul>
<li v-for='vo in list'>{{vo.username}}</li>
</ul>
</div>
</div>
</body>
<script>
var list=[
{"username":"xiaoming","pwd":123},
{"username":"xiaohong","pwd":123}
]
var vm = new Vue({
el:'#app',
data:{
list:list
}
})
</script>
demo:点击切换显示内容
效果:
代码:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>用户登录</title>
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.0.3/css/bootstrap.css" rel="stylesheet">
<script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.0.3/js/bootstrap.js"></script>
</head>
<body>
<div class="container">
<div class="page-header">
<div class="page-title">
<h1>VueLab</h1>
</div>
</div>
<div id="app">
<input type="radio" checked='checked' name="free" @click="getArticle('all')" id=""> 全部
<input type="radio" name='free' @click="getArticle('free')" id=""> 免费
<input type="radio" name="free" @click="getArticle('nofree')" id=""> 收费
<ul>
<li v-for='article in articles'>
<h4>{{article.title}}</h4>
<p>{{article.content}}</p>
</li>
</ul>
</div>
</div>
</body>
<script>
var allArt=[
{
title:'nofree',
content:'this is content',
},
{
title:'free',
content:'this is content',
}
];
var freeArt=[
{
title:'free',
content:'this is content',
}
];
var nofreeArt=[
{
title:'nofree',
content:'this is content',
}
];
var vm = new Vue({
el:'#app',
data:{
articles:''
},
mounted:function(){
this.getArticle('all');
},
methods:{
getArticle:function(msg){
if(msg=='all'){
this.articles=allArt;
}
if(msg=='free'){
this.articles=freeArt;
}
if(msg=='nofree'){
this.articles=nofreeArt;
}
}
}
})
</script>
</html>
0x02 vue单双向数据流以及事件绑定
1.vue单向数据流绑定属性值 v-bind(属性) 简写 :(属性)
例如:
<input v-bind:value="name" v-bind:class="name">
单向数据流绑定:内存中值的改变可以影响页面改变,但是页面的改变不能影响内存的改变
v-bind就是对属性的简单赋值,当内存中值改变,还是会触发重新渲染
2.vue双向数据流绑定:
在表单<input>、<textarea>以及<select> 元素控件 或者 组件 上创建双向绑定,它负责监听用户的输入事件以及更新数据
v-model 只作用于有value属性的元素,因为v-model=‘xxx’ 相当于v-bind:value='name'。如果一个元素没有value属性,那么这种设置就没有意义。
例如:
<input v-model="name" v-bind:class="name">
双向数据绑定,即只要我们在页面中修改了input的value的值,那么内存中的name的值也就被改变了。
内存中改变name的值,会影响页面重新渲染最新值。
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<!-- 2.留坑 -->
<div id='app'></div>
<!-- 1.引包 -->
<script type="text/javascript" src="vue.js"></script>
<!-- 3.实例化 -->
<script type="text/javascript">
new Vue({
el:'#app',
template:`
<div>
<!--单向数据绑定-->
<input v-bind:value="varname" v-bind:class="varname">
<!--双向数据绑定-->
<input v-model="varname" v-bind:class="varname">
</div>
`,
data:function(){
return {
varname:'hello world'
}
}
})
</script>
</body>
</html>
我们输入的数据 影响了内存 ,内存反过来再影响页面
单选框:
<body>
<div class="container">
<div class="page-header">
<div class="page-title">
<h1>VueLab</h1>
</div>
</div>
<div id="app">
男<input type="radio" name='gender' value='男' v-model="sex">
女<input type="radio" name='gender' value='女' v-model="sex">
<div class="label label-danger">{{sex}}</div>
</div>
</div>
</body>
<script>
var vm = new Vue({
el:'#app',
data:{
sex:''
},
})
</script>
复选框:
复选框mv中的数据必须定义为数组
<body>
<div class="container">
<div class="page-header">
<div class="page-title">
<h1>VueLab</h1>
</div>
</div>
<div id="app">
PHP <input type="checkbox" value="php" v-model="language">
JS <input type="checkbox" value="JS" v-model="language">
CSS <input type="checkbox" value="CSS" v-model="language">
<div class="label label-primary">{{language}}</div>
</div>
</div>
</body>
<script>
var vm = new Vue({
el:'#app',
data:{
language:[]
},
})
</script>
文本域:
<body>
<div class="container">
<div class="page-header">
<div class="page-title">
<h1>VueLab</h1>
</div>
</div>
<div id="app">
<textarea rows="" cols="" class='form-control' v-model='msg'>
</textarea>
<div class="label label-danger">
{{msg}}
</div>
</div>
</div>
</body>
<script>
var vm = new Vue({
el:'#app',
data:{
msg:''
},
})
</script>
注意:如果想要在文本域标签中插值
不要使用插值表达式,有bug,用v-text
<body>
<div class="container">
<div class="page-header">
<div class="page-title">
<h1>VueLab</h1>
</div>
</div>
<div id="app">
<textarea rows="" cols="" class='form-control' v-text='msg'>
</textarea>
<div class="label label-danger">
{{msg}}
</div>
</div>
</div>
</body>
<script>
var vm = new Vue({
el:'#app',
data:{
msg:'快来占领沙发吧!'
},
})
</script>
下拉框:
必须设置一个值为空的禁用选项,否则在IOS端有bug
<body>
<div class="container">
<div class="page-header">
<div class="page-title">
<h1>VueLab</h1>
</div>
</div>
<div id="app">
<select class='form-control' name="language" v-model='language' id="">
<option value="PHP">PHP</option>
<option value="JS">JS</option>
<option value="CSS">CSS</option>
</select>
{{language}}
</div>
</div>
</body>
<script>
var vm = new Vue({
el:'#app',
data:{
language:''
},
})
</script>
指令v-model的修饰符:
.trim 去掉空格
<body>
<div class="container">
<div class="page-header">
<div class="page-title">
<h1>VueLab</h1>
</div>
</div>
<div id="app">
<input type="text" class='form-control' v-model.trim='msg'>
{{msg.length}}
</div>
</div>
</body>
<script>
var vm = new Vue({
el:'#app',
data:{
msg:''
},
})
</script>
Demo:用户登录
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>用户登录</title>
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.0.3/css/bootstrap.css" rel="stylesheet">
<script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.0.3/js/bootstrap.js"></script>
</head>
<body>
<div class="container">
<div class="page-header">
<div class="page-title">
<h1>VueLab</h1>
</div>
</div>
<div id="app">
<!-- .prevent修饰符用来阻止表单跳转 -->
<form action="" @submit.prevent='login'>
<div class="form-group">
<label for="">用户名:</label>
<input type="text" name='username' class="form-control" v-model='user.name'>
</div>
<div class="form-group">
<label for="">密码:</label>
<input type="password" name='password' class='form-control' v-model='user.pass'>
</div>
<input type="submit" value="登录" class="btn btn-success form-control">
</form>
</div>
</div>
</body>
<script>
var vm = new Vue({
el:'#app',
data:{
user:{
name:'',
pass:''
}
},
methods:{
login:function(){
alert(this.user.name+this.user.pass);
}
}
})
</script>
</html>
3.事件绑定
v-on:事件名="表达式 || 函数名" 简写 @事件名="表达式 || 函数名"
事件名可以是原生也可以是自定义的
点赞功能
<body>
<div class="container">
<div class="page-header">
<div class="page-title">
<h1>Vue实验室</h1>
</div>
</div>
<div id="app">
<button v-on:click="count++" class="btn btn-danger">赞</button>
<p>{{count}}</p>
</div>
</div>
</body>
<script>
var vm = new Vue({
el:'#app',
data:{
count:2
}
})
</script>
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<!-- 2.留坑 -->
<div id='app'></div>
<!-- 1.引包 -->
<script type="text/javascript" src="vue.js"></script>
<!-- 3.实例化 -->
<script type="text/javascript">
new Vue({
el:'#app',
template:`
<div>
<!--单向数据绑定-->
<input v-bind:value="varname" v-bind:class="varname">
<!--双向数据绑定-->
<input v-model="varname" v-bind:class="varname">
<button v-on:click="varname='我改变了'">改变varname</button>
<button v-on:click="funChange">通过函数改变</button>
</div>
`,
data:function(){
return {
varname:'hello world'
}
},
methods:{
funChange:function(){
this.varname='改变';
}
}
})
</script>
</body>
</html>
注意:vue中的this是vue封装好给我们使用的,跟平常方法里面的this是不同的.vue中的this对应是vue实例即vm。
因为vm.$data.xxx 等价于vm.xxx,所以有些人以为this对应是data。
指令修饰符:
事件冒泡是从dom树的下面往上面冒泡
.stop可以阻止事件冒泡
.once 只触发一次
v-on:click 可以缩写:@click
@keydown.enter="xxx" 监听回车键
<body>
<div class="container">
<div class="page-header">
<div class="page-title">
<h1>Vue实验室</h1>
</div>
</div>
<div id="app">
<span v-on:click='go1'>
<span v-on:click.stop='go2'>123</span>
</span>
</div>
</div>
</body>
<script>
var vm = new Vue({
el:'#app',
data:{
count:2
},
methods:{
go1:function(msg){
alert("11111")
},
go2:function(msg){
alert("22222")
}
}
})
</script>
Demo:小说站字体放大缩小实例:
效果:
代码:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>vue实验室</title>
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.0.3/css/bootstrap.css" rel="stylesheet">
<script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.0.3/js/bootstrap.js"></script>
</head>
<body>
<div class="container">
<div class="page-header">
<div class="page-title">
<h1>Vue实验室</h1>
</div>
</div>
<div id="app">
<button class='btn btn-success' @click="size++">放大</button>
<button class="btn btn-danger" @click="size--">缩小</button>
<div style='margin-bottom:15px;'></div>
<p :style="{fontSize:size+'px'}" class='lead'>
{{msg}}
</p>
</div>
</div>
</body>
<script>
msg = `1、你永远不会知道,像我这样的人,活在世上是多么寂寞。
2、爱情本来就是突发的,只有友情才有因累积而深厚。
3、天地本就无情,若见有情,天早已荒,地早已老。
4、但是看到别的女人在被男人折磨时,她自己也会气得要命。
5、离别是为了相聚,只要能相聚,无论多痛苦的离别都可以忍受。
6、一个人若无论在什么情况下都睡得着,这人真是非常有福气。
7、经过那么多年,我还是输给了你,一败涂地。
8、一个女人的眼泪的多少,和她的身材的大小连一点关系都没有。
9、一个人到了没有钱的时候,就会把现实看得比规矩重要得多。
10、从此以后,任何一个终点,都不会再有以琛。` ;
var vm = new Vue({
el:'#app',
data:{
msg:msg,
size:20
},
})
</script>
</html>
0x03 过滤器
过滤器就是可以对我们的数据进行添油加醋然后再显示
过滤器有全局过滤器和组件内过滤器
全局过滤器Vue.filter('过滤器名',过滤方式fn);
组件内过滤器:在实例化Vue的时候,传给Vue的对象中增加一个属性filters:{'过滤器名':过滤方式fn}
使用过滤器:{{变量arg1 | 过滤器名}} arg1会作为第一个参数传给过滤器对应的函数,函数的返回值将替换该插值表达式。
实例:
组件内过滤器:反转字符串
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<div class="app">
我输入的<input type="text" name="" v-model="instring" id=""><br/>
我输出的{{instring}}
过滤器:{{instring | reversal('我是第二个参数')}}
</div>
<script src="vue.js"></script>
<script>
new Vue({
el:'.app',
data:function(){
return {
instring:''
}
},
filters:{
reversal:function(strVal,arg2){
// 首先按字符将字符串拆成数组,然后将数组倒转,然后将倒转后数组拼成字符串
return arg2+strVal.split('').reverse().join('');
}
}
})
</script>
</body>
</html>
解释:
全局过滤方式:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<div class="app">
我输入的<input type="text" name="" v-model="instring" id=""><br/>
我输出的{{instring}}
过滤器:{{instring | reversal('我是第二个参数')}}
</div>
<script src="vue.js"></script>
<script>
Vue.filter('reversal',function(strVal,arg2){
return arg2+strVal.split('').reverse().join('');
})
new Vue({
el:'.app',
data:function(){
return {
instring:''
}
},
// filters:{
// reversal:function(strVal,arg2){
// // 首先按字符将字符串拆成数组,然后将数组倒转,然后将倒转后数组拼成字符串
// return arg2+strVal.split('').reverse().join('');
// }
// }
})
</script>
</body>
</html>
0x04 计算属性和侦听器
watch监听单个 ,computed监听多个
业务场景:
1.例如淘宝,当用户输入某个人名的时候,就会触发某个效果
2.利用Vue做一个简单的计算器。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<div id="app">
<input type="text" v-model="msg">
</div>
<script src="vue.js"></script>
<script>
new Vue({
el:'#app',
data:{
msg:''
},
// 监听msg的值
watch:{
// msg原来的值会自动传给第二个参数,新值会自动传给第一个参数
msg:function(new_msg,old_msg){
if(new_msg=='love'){
alert('i love you');
}
}
}
})
</script>
</body>
</html>
当watch监听的是复杂数据类型的时候上面的这种写法就不起作用了。需要做深度监听(写法如下)
在watch:{ }中 需要这么写:
监听的变量名:一个对象,对象里面一个方法handler 对应的相关的处理函数,一个属性depp 值为true表示开启深度监听。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<div id="app">
<input type="text" placeholder="姓名" v-model="msg.name">
<input type="text" name="" id="" placeholder="请输入你的年龄" v-model="msg.age">
<input type="text" placeholder="学校" v-model="msg.school">
</div>
<script src="vue.js"></script>
<script>
new Vue({
el:"#app",
data:{
msg:{
name:'xiaoming',
age:'13',
school:'xdu'
}
},
watch:{
msg:{
handler:function(new_msg,old_msg){
if(Number(new_msg.age)>18){
alert('可以进入观看');
}else{
alert('你太小了');
}
},
deep:true//开启深度监听
}
}
})
</script>
</body>
</html>
<body>
<div class="container">
<div class="page-header">
<div class="page-title">
<h1>VueLab</h1>
</div>
</div>
<div id="app">
<form action="">
<label for="">用户名:</label>
<input type="text" class='form-control' name='username' v-model.lazy='username'>
<p :class='color'>{{msg}}</p>
</form>
</div>
</div>
</body>
<script>
var vm = new Vue({
el:'#app',
data:{
msg:'',
username:'',
color:''
},
watch:{
username:function(){
if(this.username=="光谷小五郎"){
this.msg='该用户已注册';
this.color='text-danger';
}else{
this.msg='恭喜你,可以注册该用户名';
this.color='text-success';
}
}
}
})
</script>
Demo1:购物车满200减100
<body>
<div class="container">
<div class="page-header">
<div class="page-title">
<h1>VueLab</h1>
</div>
</div>
<div id="app">
<form action="">
<div class="form-group">
<label for="">单价:</label>
<input type="text" class='form-control' v-model='price'>
</div>
<div class="form-group">
<label for="">数量</label>
<input type="text" class='form-control' v-model='num'>
</div>
</form>
<p>总价:{{sum}}</p>
</div>
</div>
</body>
<script>
var vm = new Vue({
el:'#app',
data:{
price:0,
num:0,
},
computed:{
sum:function(){
if(this.price<0){
this.price=0;
}
if(this.num<0){
this.num=0
}
if(this.num*this.price>199){
return this.num*this.price-100;
}else{
return this.num*this.price;
}
}
}
})
</script>
实现方式二: 代码冗余,不够优雅
<body>
<div class="container">
<div class="page-header">
<div class="page-title">
<h1>VueLab</h1>
</div>
</div>
<div id="app">
<form action="">
<div class="form-group">
<label for="">单价:</label>
<input type="text" class='form-control' v-model='price'>
</div>
<div class="form-group">
<label for="">数量</label>
<input type="text" class='form-control' v-model='num'>
</div>
</form>
<p>总价:{{sum}}</p>
</div>
</div>
</body>
<script>
var vm = new Vue({
el:'#app',
data:{
price:0,
num:0,
},
watch:{
price:function(){
sum = this.price*this.num;
this.sum = sum>199?sum-100:sum;
},
num:function(){
sum = this.price*this.num;
this.sum = sum>199?sum-100:sum;
}
}
})
</script>
Demo2:简单计算器
computed 可以监视多个data中的变量,只要定义在computed里面的函数中包含了该变量,一旦该变量发生改变,都会触发当前函数。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<div id="app">
(<input type="text" v-model='var1'>+<input type="text" v-model="var2">)* <input type="text" v-model="var3"> = {{result}};
</div>
<script src="vue.js"></script>
<script>
new Vue({
el:'#app',
data:{
var1:'',
var2:'',
var3:'1'
},
computed:{
result:function(){
return (Number(this.var1)+Number(this.var2))*Number(this.var3);
}
}
})
</script>
</body>
</html>