v-model:实现双向绑定,常用于表单元素。
- 如果要让多个单选框成为一组,必须保证 v-model的值必须相等。
- 当data中的数据发送变化时,对应的单选框就会被选中 选中单选框的时候,data中的数据也会跟着变化,变成单选框中value的属性值。
实例:单选框
<div id="app">
选择一个你喜欢的明星:<br>
<!-- input后面的文字 只是对input元素的解释说明,是给用户看到。 input的值由它的value属性来决定 -->
<input type="radio" v-model="inputData" value="成龙">成龙<br>
<input type="radio" v-model="inputData" value="吴彦祖">吴彦祖<br>
<input type="radio" v-model="inputData" value="李小龙">李小龙<br>
</div>
<script src="vue.js"></script>
<script>
new Vue({
el:"#app",
data:{
//空会转化为false
inputData:""
},
methods:{
}
})
</script>
复选框:在vue中复选框的时候可以分为单独使用和组合使用。
- 单独使用: 比如 同意协议 data中绑定的数据是一个布尔值, 选中的时候,值为true,反之为false。
- 组合使用:v-model需要和value一起使用,同时绑定的数据必须是一个数组类型。 同一组的复选框必须绑定同一个数据。
实例:多选框
<div id="app">
<!-- <input type="checkbox" v-model="isChecked"> 同意协议<br>
<p>选择的状态:{{isChecked}}</p> -->
<p>选择您喜欢的电视剧</p>
<input type="checkbox" v-model="checkData" value="雪中悍刀行">雪中悍刀行<br>
<input type="checkbox" v-model="checkData" value="风起洛阳">风起洛阳<br>
<input type="checkbox" v-model="checkData" value="小敏家">小敏家<br>
<input type="checkbox" v-model="checkData" value="谁是凶手">谁是凶手<br>
<input type="checkbox" v-model="checkData" value="对手">对手<br>
<p>您选择的是:{{checkData}}</p>
</div>
<script src="vue.js"></script>
<script>
new Vue({
el:"#app",
data:{
isChecked:false,
//写到数组里面的会被默认选中
checkData:["对手","风起洛阳"]
},
methods:{
}
})
下拉框也分为单选和多选
- 多选的话,在select上添加一个 multipe属性 即可。
- 多选绑定的值是一个数组。 使用 ctrl+鼠标单击 选择。
案例:下拉框
<div id="app">
<!-- option中有value时,数据会优先匹配value中的值,没有value匹配的是option中的文本 -->
<!-- 下拉框的数据绑定是绑定在select标签上的 -->
请选择喜欢的电视剧:
<select v-model="selectData" multiple>
<option value="">--请选择--</option>
<option value="雪中焊道行">雪中焊道行</option>
<option value="谁是凶手">谁是凶手</option>
<option value="小明家">小明家</option>
<option value="对手">对手</option>
</select>
<p>{{selectData}}</p>
</div>
<script src="vue.js"></script>
<script>
new Vue({
el:"#app",
data:{
selectData:"谁是凶手"
},
methods:{
}
})
</script>
表单的修饰符 用v-model
示例:修饰符
<div id="app">
用户名:<input type="text" v-model="username">
年龄:<input type="text" v-model="age">
{{age}}
</div>
<script src="vue.js"></script>
<script>
new Vue({
el:"#app",
data:{
username:"lisi",
age:20
},
methods:{
}
})
</script>
vue中的key
每当数组中的数据发送变化时,我们都需要重新渲染页面:
1.直接全部重新渲染。 代码实现简单,但是效率低。
2.一一对比,找到被删除的DOM,将其删除,其他人不动。 执行效率比较高。、
vue使用的就是第二个方案,叫做虚拟DOM。 vue2.0引入的,渲染速度提高了2-4倍。
**
**
key的案例: 防止删除时候数据乱掉
<div id="app">
<from>
<p>书名:<input type="text" v-model="bookName"></p>
<p><input type="submit" value="添加" @click.prevent="add"></p>
</from>
<ul>
<li v-for="(item,index) in books" v-bind:key="item.id"><input type="checkbox" > {{item.name}} <button @click="del(index)">删除</button></li>
</ul>
</div>
<script src="vue.js"></script>
<script>
//创建Vue实例,得到 ViewModel
new Vue({
el: "#app",
data: {
id: 4,
bookName: "",
books: [
{ id: 1, name: "明克街13号" },
{ id: 2, name: "我的云养女友" },
{ id: 3, name: "星门" }
]
},
methods: {
//点击 添加
add(){
let book = {id:this.id,name:this.bookName};
//添加books中
this.books.push(book);
this.bookName="";
},
del(i){
//实现删除功能
this.books.splice(i,1);
}
}
})
选项卡案例
css样式
<style>
* {
padding: 0;
margin: 0;
}
ul {
list-style: none;
}
#app {
width: 480px;
margin: 20px auto;
border: 1px solid cornflowerblue;
}
ul {
width: 100%;
overflow: hidden;
}
ul li {
float: left;
width: 160px;
height: 60px;
line-height: 60px;
text-align: center;
background-color: #cccccc;
}
ul li a {
text-decoration: none;
color: black;
}
p {
height: 200px;
text-align: center;
line-height: 200px;
background-color: #fff;
}
li.active {
background-color: cornflowerblue;
}
/* 有这个类名的p标签,显示 */
p.active {
display: block;
}
img {
width: 100%;
}
</style>
body部分
<div id="app">
<ul>
<!-- 使用v-for遍历生成 li标签 -->
<!-- :class中可以写三元(index==cur?'active':''),也可以写方法 -->
<li :class="isActive(index)" v-for="(item,index) in list" :key="item.id" @click="toggle(index)">
<!-- item表示循环的当前元素, 使用插值显示在页面上-->
<a href="#">{{item.name}}</a>
</li>
</ul>
//为真则显示图片 为假则隐藏
<p v-show="index==cur" v-for="(item,index) in list" :key="item.id">
<img :src="item.img" alt="">
</p>
</div>
script代码
<!--
1.将所有的图片都隐藏
2.默认第一个按钮有激活的样式
3.点击哪一个按钮,给哪一个按钮添加激活样式
-->
<script src="vue.js"></script>
<script>
new Vue({
el: "#app",
data: {
//显示的元素的索引
cur:0,
list: [{
id: 1,
name: "鞠婧祎",
img: "./img/1.jpg"
}, {
id: 2,
name: "李沁",
img: "./img/2.jpg"
}, {
id: 3,
name: "易烊千玺",
img: "./img/3.jpg"
}]
},
methods: {
//判断小li是否激活
isActive(index){
return index==this.cur?"active":"";
},
// 点击li标签改变cur的值,实现切换效果
// index是接受上面 @click中方法传递过来的index。
toggle(index){
this.cur = index;
}
}
})
</script>
案例:待办事项
实现功能
1.用户输入待办事项,回车后添加到“正在进行”,并清空文本框 √
2.在“正在进行”列表中单击列表项,添加到 已完成 列表 √
3.在“已经完成”列表中单击列表项,添加到 正在进行 列表 √
4.在响应列表项中点击 删除 删除 该项目。
css部分
body {
margin: 0;
padding: 0;
font-size: 16px;
background: #CDCDCD;
}
header {
height: 50px;
background: #333;
background: rgba(47, 47, 47, 0.98);
}
section {
margin: 0 auto;
}
label {
float: left;
width: 100px;
line-height: 50px;
color: #DDD;
font-size: 24px;
cursor: pointer;
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
}
header input {
float: right;
width: 60%;
height: 24px;
margin-top: 12px;
text-indent: 10px;
border-radius: 5px;
box-shadow: 0 1px 0 rgba(255, 255, 255, 0.24), 0 1px 6px rgba(0, 0, 0, 0.45) inset;
border: none
}
input:focus {
outline-width: 0
}
h2 {
position: relative;
}
span {
position: absolute;
top: 2px;
right: 5px;
display: inline-block;
padding: 0 5px;
height: 20px;
border-radius: 20px;
background: #E6E6FA;
line-height: 22px;
text-align: center;
color: #666;
font-size: 14px;
}
ol,
ul {
padding: 0;
list-style: none;
}
li input {
position: absolute;
top: 2px;
left: 10px;
width: 22px;
height: 22px;
cursor: pointer;
}
p {
margin: 0;
}
li p input {
top: 3px;
left: 40px;
width: 70%;
height: 20px;
line-height: 14px;
text-indent: 5px;
font-size: 14px;
}
li {
height: 32px;
line-height: 32px;
background: #fff;
position: relative;
margin-bottom: 10px;
padding: 0 45px;
border-radius: 3px;
border-left: 5px solid #629A9C;
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.07);
}
ol li {
cursor: move;
}
ul li {
border-left: 5px solid #999;
opacity: 0.5;
}
li a {
position: absolute;
top: 2px;
right: 5px;
display: inline-block;
width: 14px;
height: 12px;
border-radius: 14px;
border: 6px double #FFF;
background: #CCC;
line-height: 14px;
text-align: center;
color: #FFF;
font-weight: bold;
font-size: 14px;
cursor: pointer;
}
li button{
position: absolute;
right: 10px;
top: 50%;
transform: translateY(-50%);
}
footer {
color: #666;
font-size: 14px;
text-align: center;
}
@media screen and (max-device-width: 620px) {
section {
width: 96%;
padding: 0 2%;
}
}
@media screen and (min-width: 620px) {
section {
width: 600px;
padding: 0 10px;
}
}
div部分
<div id="app">
<header>
<section>
<label for="title">ToDoList</label>
<input type="text" v-model="thing" placeholder="添加ToDo" required="required" autocomplete="off"
@keydown.13="add" />
</section>
</header>
<section>
<h2>正在进行 <span>{{ongoing.length}}</span></h2>
<ol id="todolist" class="demo-box">
<li v-for="(item,index) in ongoing" :key="item.id">
<input type="checkbox" @click="addToDone(index)">
{{item.title}}
<button @click="delGoing(index)">删除</button>
</li>
</ol>
<h2>已经完成 <span>{{done.length}}</span></h2>
<ul id="donelist">
<li v-for="(item,index) in done " :key="item.id">
<input type="checkbox" checked @click="addToGoing(index)">
{{item.title}}
<button @click="delDone(index)">删除</button>
</li>
</ul>
</section>
</div>
<footer>
Copyright © 2021 todolist.cn
</footer>
js代码
<script>
//创建Vue实例,得到 ViewModel
var vm = new Vue({
el: '#app',
data: {
id: 4,
//存储用户输入的信息
thing: "",
//正在进行 列表
ongoing: [{
id: 1,
title: "吃饭"
}, {
id: 2,
title: "睡觉"
}],
//已经完成 列表
done: [{
id: 3,
title: "打豆豆"
}]
},
methods: {
//添加到待办事项
add() {
//组装一个对象,将对象添加到ongoing数组中。
let obj = {
id: this.id,
title: this.thing
};
//新的对象产生,id自增,防止id重复。
this.id++;
this.ongoing.push(obj);
//将thing的值设置为空,则输入框自动清空
this.thing = "";
},
//添加到已经完成
addToDone(index) {
//将点击的数据 从ongoing 删除,添加到 Done中
//splice(index,1)从index开始,删除一个元素。 splice会返回被删除的元素组成的数组。
this.done.push(this.ongoing.splice(index,1)[0]);
},
//添加到 正在进行
addToGoing(index){
this.ongoing.push(this.done.splice(index,1)[0]);
},
//从正在进行中删除
delGoing(index){
this.ongoing.splice(index,1);
},
//从已经完成中删除
delDone(index){
this.done.splice(index,1);
}
}
});
</script>
案例:模态框
需求:
点击点赞 弹出登录页面
css部分
<style>
#model-box {
position: fixed;
left: 0;
top: 0;
right: 0;
bottom: 0;
background-color: rgba(0, 0, 0, .2);
display: flex;
justify-content: center;
align-items: center;
}
#center {
width: 300px;
height: 150px;
background-color: aliceblue;
display: flex;
flex-direction: column;
justify-content: space-evenly;
}
#center div {
text-align: center;
}
</style>
div部分
<div id="app">
<button @click="like">点赞</button>
<!-- .self:事件必须准确在自身触发才会执行事件处理函数。 -->
<div id="model-box" v-show="isShow" @click.self="hideModel">
<div id="center">
<div>
用户名<input type="text">
</div>
<!-- 可以在键盘事件中,使用按键修饰符, .按钮对应的code码 -->
<div>
密 码<input type="password" @keydown="login">
</div>
<div>
<button>登录</button>
</div>
</div>
</div>
</div>
js部分
<script src="./vue.js"></script>
<script>
new Vue({
el: "#app",
data: {
isShow:false
},
// 方法
methods: {
like() {
//将isShow的值变为true,则模态框就会显示
this.isShow = true;
},
hideModel() {
//点击登录窗口以外的区域,隐藏 模态框
this.isShow = false;
},
login(event) {
console.log(event.keyCode);
alert("登录")
}
}
})
</script>
简单购物车的实现
css部分
<style>
tr td {
width: 90px;
height: 30px;
border: 1px solid gray;
text-align: center;
}
tr td a {
text-decoration: none;
text-align: center;
display: flex;
width: 20px;
height: 20px;
background-color: rgba(0, 0, 0, 0.2);
justify-content: space-evenly;
}
.five {
display: flex;
justify-content: space-evenly;
align-items: center;
}
.sum {
width: 160px;
height: 30px;
background-color: grey;
display: flex;
color: #fff;
text-align: center;
}
.center {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
font-size: 48px;
}
</style>
body部分
<div id="app">
<table v-show="isShow">
<tr>
<td></td>
<td>书籍名称</td>
<td>出版日期</td>
<td>价格</td>
<td>购买数量</td>
<td>小计</td>
<td>操作</td>
</tr>
<tr v-for="(item,index) in datas" :key="item.id">
<td>{{item.id}}</td>
<td>{{item.name}}</td>
<td>{{item.time}}</td>
<td>${{item.price}}</td>
<td class="five"><a href="#" @click="cut_down(index)">-</a>{{item.total}}<a href="#"
@click="add_a(index)">+</a></td>
<td>${{item.sum}}</td>
<td><button @click="del(index)">删除</button></td>
</tr>
</table>
<div class="sum" v-show="isShow">
总和: <i>{{isSum}}</i>
</div>
<div class="center">{{msg}}</div>
</div>
js部分
<script src="vue.js"></script>
<script>
new Vue({
el: "#app",
data: {
msg: "",
isShow: "false",
datas: [{
id: 1,
name: "算法",
time: "2006-9",
price: "85.00",
sum: 85.00,
total: 1
}, {
id: 2,
name: "unix",
time: "2020-9",
price: "59.00",
sum: 59.00,
total: 1
}, {
id: 3,
name: "编程",
time: "2016-9",
price: "39.00",
sum: 39.00,
total: 1
}]
},
methods: {
//减
cut_down(index) {
if (this.datas[index].total != 1) {
this.datas[index].total -= 1;
this.datas[index].sum = (this.datas[index].total) * this.datas[index].price
} else {
alert("不能再减少了")
}
},
//增加
add_a(index) {
this.datas[index].total += 1;
this.datas[index].sum = (this.datas[index].total) * this.datas[index].price
},
del(index) {
this.datas.splice(index, 1);
}
},
//计算属性
computed: {
isSum() {
let issum = 0;
for (var i = 0; i < this.datas.length; i++) {
issum += this.datas[i].sum;
}
if (this.datas.length < 1) {
this.isShow = false;
this.msg = "你的购物车为空"
}
return issum
}
}
})
</script>