24
v-if 和v-show区别
v-if 是真正的条件渲染,因为它会确保在切换过程中条件块内的事件监听器和子组件适当的销毁重建
v-show不管初始条件是什么,元素总是会被渲染,并且只是简单基于css进行切换
v-show适用于页面多次切换;
小案例:登录方式切换
v-if方式
<!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>
<script src="js/vue.js"></script>
</head>
<body>
<div id ="app">
<div v-if="logintype === 'phone'">
<label >手机:</label>
<input type="text" placeholder="请输入手机号"><br>
<label >密码:</label>
<input type="password" placeholder="请输入密码">
</div>
<div v-else-if="logintype === 'email'">
<label >email:</label>
<input type="text" placeholder="请输入邮箱"><br>
<label >密码:</label>
<input type="password" placeholder="请输入密码">
</div>
<button @click="change">切换登录方式</button>
</div>
<script>
const app = Vue.createApp({
data() {
return{
logintype:'phone'
}
},
methods: {
change(){
this.logintype === 'phone'? this.logintype ='email': this.logintype ='phone'
}
}
}).mount('#app');
</script>
</body>
</html>
点击后会切换
v-show方式
<div v-show="logintype === 'phone'">
<label >手机:</label>
<input type="text" placeholder="请输入手机号"><br>
<label >密码:</label>
<input type="password" placeholder="请输入密码">
</div>
<div v-show="logintype === 'email'">
<label >email:</label>
<input type="text" placeholder="请输入邮箱"><br>
<label >密码:</label>
<input type="password" placeholder="请输入密码">
</div>
<button @click="change">切换登录方式</button>
区别:当写完后切换,再切换回来原数据还是保留的
v-for 遍历数组
其中index,是数组自带的序列,在开发中很常见
<!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>
<script src="js/vue.js"></script>
</head>
<body>
<div id ="app">
<!-- 遍历数组里的对象-->
<ul>
<li v-for="(p,index) in personArr">{{index}}--{{p}}</li>
</ul>
<p>--------------</p>
<!-- 遍历对象 -->
<ul>
<li v-for ="(p,index) in persons">{{index}}--{{p}}---{{p.name}}</li>
</ul>
</div>
<script>
const app = Vue.createApp({
data() {
return{
personArr:['哈哈',20,'你好啊'],
persons:[
{name:'sana',age:20,add:'上海'},
{name:'anna',age:10,add:'北京'},
{name:'tina',age:30,add:'深圳'},
]
}
},
methods: {}
}).mount('#app');
</script>
</body>
</html>
v-for 遍历对象
<!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>
<script src="js/vue.js"></script>
</head>
<body>
<div id ="app">
<ul>
<li v-for="item in preson">{{item}}</li>
</ul>
<p>--------</p>
<ul>
<li v-for="item,key in preson">{{key}}:{{item}}</li>
</ul>
<ul>
<li v-for="item,key,index in preson">{{index}}--{{key}}:{{item}}</li>
</ul>
</div>
<script>
const app = Vue.createApp({
data() {
return{
preson:{
name:'sana',
age:18,
friends:['张三','李四']
}
}
},
methods: {}
}).mount('#app');
</script>
</body>
</html>
v-if 和v-for 优先级对比
在2.0版本中 v-for 优先
在3.0版本中v-if优先
最好两个不要同时使用
v-for 案例
js函数参考链接:indexOf()
js函数参考链接:sort()
深度拷贝参考链接
深度拷贝参考链接2
<!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>
<script src="js/vue.js"></script>
<style>
body{
text-align: center;
}
ul li{
list-style: none;
line-height: 40px;
}
</style>
</head>
<body>
<div id ="app">
<h3>搜索列表</h3>
<label><input v-model="searchStr" type="text" placeholder="输入搜索的姓名"></label>
<div>
<h3>排序</h3>
<button @click="setOrderType(2)">age升序</button>
<button @click="setOrderType(1)">age降序</button>
<button @click="setOrderType(0)">还原</button>
</div>
<ul>
<li v-for="(p,index) in filterPerson">
{{index +1}}姓名:{{p.name}},性别:{{p.sex}},年龄:{{p.age}},手机:{{p.phone}}
</li>
</ul>
</div>
<script>
const app = Vue.createApp({
data() {
return{
persons:[
{name:'张三',sex:'女',age:16,phone:'12344321'},
{name:'李四',sex:'男',age:30,phone:'74634646'},
{name:'王五',sex:'女',age:20,phone:'32534688'},
{name:'吕一',sex:'男',age:41,phone:'98997866'},
{name:'赵云',sex:'男',age:60,phone:'34578734'}
],
searchStr:"",
// flag: 0:默认 ;1升序 ;2降序
ordertype:0
}
},
computed: {
// 最常发生变化的是person数组
filterPerson(){
// 1、取出相关的属性
const {persons,searchStr,ordertype} = this;
// 2、定义过滤数组(深度拷贝成一个新的数组(这样两个数组互不影响))
let arr=[...persons];
// 3、根据条件过滤
// trim去掉两边空格
if(searchStr.trim()){
arr = persons.filter((p)=>{
// indexOf() 方法可返回某个指定的字符串值在字符串中首次出现的位置。找不到返回-1
return p.name.indexOf(searchStr) !==-1;
})
}
// 4、排序
if(ordertype){
arr.sort((p1,p2)=>{
// console.log(p1,p2);
if(ordertype === 1){
return p2.age - p1.age;
}
else{
return p1.age - p2.age;
}
})
}
// 返回过滤后的数组
return arr;
}
},
methods: {
setOrderType(ordertype){
this.ordertype = ordertype;
}
}
}).mount('#app');
</script>
</body>
</html>
效果:可按照搜索值进行排序,点击降序、升序按年龄排序,还原清除排序
正常数据
搜索
升序
绑定key的原因和条件
当for循环后,需要插入或者修改其中一个,key作为作为标识,key最好是数字或者字符串类型
绑定key的条件,往中间或者头部追加或者修改,或者对记录需要做内部处理等情景下
例如
<ul>
<li v-for="(p,index) in filterPerson" :key="id">
{{index +1}}姓名:{{p.name}},性别:{{p.sex}},年龄:{{p.age}},手机:{{p.phone}}
</li>
</ul>
绑定key可用于避免bug
例如未绑定key的话,插入后选择的会发生移位
例子:
<!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>
<script src="js/vue.js"></script>
</head>
<body>
<div id ="app">
<div>
<label>ID:<input type="text" v-model="id" ></label>
<label>Name:<input type="text" v-model="name"></label>
<button @click="add">添加</button>
</div>
<ul>
<li v-for="item in listarr" :key="item.id">
<input type="checkbox">
{{item.id}} ---- {{item.name}}
</li>
</ul>
</div>
<script>
const app = Vue.createApp({
data() {
return{
id:'',
name:'',
listarr:[
{id:1,name:'张三'},
{id:2,name:'李四'},
{id:3,name:'王五'},
{id:4,name:'赵六'},
{id:5,name:'刘七'},
]
}
},
methods: {
add(){
// 尾部追加
// this.listarr.push({id:this.id,name:this.name},)
// 头部追加
// this.listarr.unshift({id:this.id,name:this.name},)
// 中间追加
// splice()从第二个开始,删除0条
this.listarr.splice(2,0,{id:this.id,name:this.name},)
}
}
}).mount('#app');
</script>
</body>
</html>
当插入了key值可以用于识别时
v-model的基础使用-实现表单元素和数据的双向绑定
表单-数据双向绑定
内部实现原理:先绑定一个值获取输入内容,在通过input自动的input时间动态输出event.target
<!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>
<script src="js/vue.js"></script>
</head>
<body>
<div id ="app">
<input type="text" :value="msg" @input="valuechange">
<!-- 简写方式 -->
<input type="text" :value="msg" @input="msg=$event.target.value">
<h1>{{msg}}</h1>
</div>
<script>
const app = Vue.createApp({
data() {
return{
msg:'hello'
}
},
methods: {
valuechange(event){
this.msg = event.target.value;
}
}
}).mount('#app');
</script>
</body>
</html>
v-model常见操作
v-model 单选
两个选项只能选择其中一个,选择了就在下方显示值
<!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>
<script src="js/vue.js"></script>
</head>
<body>
<div id ="app">
<label><input type="radio" value="男" name="sex" v-model="sex">男</label>
<label><input type="radio" value="女" name="sex" v-model="sex">女</label>
<p>-------------</p>
<h2>选择的性别是{{sex}}</h2>
</div>
<script>
const app = Vue.createApp({
data() {
return{
// 默认是男
sex:'男',
}
},
methods: {}
}).mount('#app');
</script>
</body>
</html>
v-model 多选
<!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>
<script src="js/vue.js"></script>
</head>
<body>
<div id ="app">
<!-- 1、勾选1个 -->
<label ><input type="checkbox" v-model="isagree">同意xxx协议</label>
<h2>是否同意协议:{{isagree?'同意':'不同意'}}</h2>
<button :disabled="!isagree">注册</button>
<p>========</p>
<!-- 多选 -->
<label>兴趣爱好</label>
<input type="checkbox" value="篮球" v-model="habits">篮球
<input type="checkbox" value="足球" v-model="habits">足球
<input type="checkbox" value="羽毛球" v-model="habits">羽毛球
<input type="checkbox" value="乒乓球" v-model="habits">乒乓球
<h2>用户的兴趣爱好:{{habits}}</h2>
<!--值绑定 -->
<label v-for="star in starts" :for="star">
<input type="checkbox" :value="star" :id="star" v-model="like">{{star}}
</label>
<h2>用户的兴趣爱好:{{like}}</h2>
</div>
<script>
const app = Vue.createApp({
data() {
return{
isagree:false,
habits:[],
starts:['周杰伦','蔡依林','刘德华'],
like:[]
}
},
methods: {}
}).mount('#app');
</script>
</body>
</html>
例子1:同意时,注册按钮可选择,常用于前端页面
例子2:多选,动态获取值,可用于服务器进行交互
例子3:更符合开发过程中,数据由后端提供,用变量注入,可以更方便的展示
v-model下拉
<!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>
<script src="js/vue.js"></script>
</head>
<body>
<div id ="app">
<p>选择所在城市</p>
<select name="city" v-model="city">
<option value="上海">上海</option>
<option value="北京">北京</option>
<option value="南京">南京</option>
</select>
<p>选择的城市是:{{city}}</p>
<p>=========================</p>
<p>选择所在城市</p>
<select name="citys" v-model="citys" multiple>
<option value="上海">上海</option>
<option value="北京">北京</option>
<option value="南京">南京</option>
</select>
<p>选择的城市是:{{citys}}</p>
</div>
<script>
const app = Vue.createApp({
data() {
return{
city:'北京',
citys:[]
}
},
methods: {}
}).mount('#app');
</script>
</body>
</html>
例子1:下拉单选,动态切换选择的
例子2:下拉多选,进行展示
v-model 使用修饰符
<!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>
<script src="js/vue.js"></script>
</head>
<body>
<div id ="app">
<!-- 1、lazy -->
<input type="text" v-model.lazy="msg">
<h1>{{msg}}</h1>
<!-- 2、number -->
<input type="number" v-model.number="age">
<h1>{{age}}=={{typeof age}}</h1>
<!-- 3、trim -->
<input type="text" v-model.trim="name">
<h1>xxx{{name}}xxx</h1>
</div>
<script>
const app = Vue.createApp({
data() {
return{
msg:"hello",
age:18,
name:''
}
},
methods: {}
}).mount('#app');
</script>
</body>
</html>
lazy 可用于输入完之后再展示,避免频繁切换
number 强制为数字类型
trim 去除前后空格
指令小案例
先搭建静态页面
<!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>
<script src="js/vue.js"></script>
</head>
<style>
#app{
margin: 50px auto;
width: 600px;
}
fieldset{
border:1px solid purple;
margin-bottom: 20px;
}
fieldset input{
width: 200px;
height: 30px;
margin: 10px 0;
}
table{
width: 600px;
border:2px solid purple;
text-align: center;
}
thead{
background-color: purple;
color: #fff;
}
</style>
<body>
<div id ="app">
<fieldset>
<legend>信息录入系统(vue)</legend>
<div>
<label>姓名:<input type="text" placeholder="姓名"></label>
</div>
<div>
<label>年龄:<input type="text" placeholder="年龄:"></label>
</div>
<div>
<label>性别:
<select>
<option value="男">男</option>
<option value="女">女</option>
</select>
</label>
</div>
<div>
<label>手机:<input type="text" placeholder="手机"></label>
</div>
<button>创建新用户</button>
</fieldset>
<!-- 下部分 -->
<table>
<thead>
<tr>
<td>姓名</td>
<td>性别</td>
<td>年龄</td>
<td>手机</td>
<td>删除</td>
</tr>
</thead>
<tbody>
<tr>
<td>续航三</td>
<td>男</td>
<td>23</td>
<td>12414</td>
<td><button>删除</button></td>
</tr>
</tbody>
</table>
</div>
<script>
const app = Vue.createApp({
data() {
return{
persons:[
{name:'jack',age:20,sex:'男',phone:'12345567'},
{name:'lily',age:17,sex:'女',phone:'54256445'},
{name:'sana',age:51,sex:'男',phone:'84624145'},
]
}
},
methods: {}
}).mount('#app');
</script>
</body>
</html>
表单进行渲染,绑定事件,点击删除能删除
<!-- 下部分 -->
<table>
<thead>
<tr>
<td>姓名</td>
<td>性别</td>
<td>年龄</td>
<td>手机</td>
<td>删除</td>
</tr>
</thead>
<tbody>
<tr v-for="(p,index) in persons" :key="id">
<td>{{p.name}}</td>
<td>{{p.sex}}</td>
<td>{{p.age}}</td>
<td>{{p.phone}}</td>
<td><button @click="delP(index)">删除</button></td>
</tr>
</tbody>
</table>
</div>
<script>
const app = Vue.createApp({
data() {
return{
persons:[
{id:1,name:'jack',age:20,sex:'男',phone:'12345567'},
{id:2,name:'lily',age:17,sex:'女',phone:'54256445'},
{id:3,name:'sana',age:51,sex:'男',phone:'84624145'},
]
}
},
methods: {
// 传递下标来识别,进行操作
delP(index){
this.persons.splice(index,1);
}
}
}).mount('#app');
</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>
<script src="js/vue.js"></script>
</head>
<style>
#app{
margin: 50px auto;
width: 600px;
}
fieldset{
border:1px solid purple;
margin-bottom: 20px;
}
fieldset input{
width: 200px;
height: 30px;
margin: 10px 0;
}
table{
width: 600px;
border:2px solid purple;
text-align: center;
}
thead{
background-color: purple;
color: #fff;
}
</style>
<body>
<div id ="app">
<fieldset>
<legend>信息录入系统(vue)</legend>
<div>
<label>姓名:<input type="text" placeholder="姓名" v-model.trim="newperson.name"></label>
</div>
<div>
<label>年龄:<input type="text" placeholder="年龄:" v-model.trim="newperson.age"></label>
</div>
<div>
<label>性别:
<select v-model="newperson.sex">
<option value="男">男</option>
<option value="女">女</option>
</select>
</label>
</div>
<div>
<label>手机:<input type="text" placeholder="手机" v-model.trim="newperson.phone"></label>
</div>
<button @click="addnewp">创建新用户</button>
</fieldset>
<!-- 下部分 -->
<table>
<thead>
<tr>
<td>姓名</td>
<td>性别</td>
<td>年龄</td>
<td>手机</td>
<td>删除</td>
</tr>
</thead>
<tbody>
<tr v-for="(p,index) in persons" >
<td>{{p.name}}</td>
<td>{{p.sex}}</td>
<td>{{p.age}}</td>
<td>{{p.phone}}</td>
<td><button @click="delP(index)">删除</button></td>
</tr>
</tbody>
</table>
</div>
<script>
const app = Vue.createApp({
data() {
return{
persons:[
{id:1,name:'jack',age:20,sex:'男',phone:'12345567'},
{id:2,name:'lily',age:17,sex:'女',phone:'54256445'},
{id:3,name:'sana',age:51,sex:'男',phone:'84624145'},
],
newperson:[
{name:'',age:'',sex:'',phone:''},
]
}
},
methods: {
// 传递下标来识别,进行操作
delP(index){
this.persons.splice(index,1);
},
// 增加一条新记录
addnewp(){
const {name,age,sex,phone}=this.newperson;
// 1、判断
if(!name||!age||!sex||!phone){
alert("输入数据不完整")
return
}
// 2、插入一条新纪录
this.persons.unshift(this.newperson)
// 3、清空
this.newperson=""
}
}
}).mount('#app');
</script>
</body>
</html>