1、Vue实现购物车
-
核心:
- 每个列表先需要添加一个check属性,用于选中。 注意使用 $set进行添加,不然不会响应
- watch监听数组的变化
- 注意不要使用 computed对数组进行加工。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>原生JS实现购物车功能</title> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> </head> <body> <table align="center" width="600" border="1" id="app"> <thead> <tr> <td>全选 <input type="checkbox" :checked="isallCheck" @click="allcheck" ></td> <td>名称</td> <td>价格</td> <td>数量</td> <td>小计</td> <td>操作</td> </tr> </thead> <tbody> <tr v-for="(item,index) in arr" :key="index"> <td> <input type="checkbox" @click="rowCheck(item,$event)" :checked="item.check" > </td> <td>{{item.title}}</td> <td>{{item.price}}</td> <td> <button @click="reduce(item)">-</button> <input type="text" style="width:40px;text-align:center;" :value="item.nums"> <button @click="add(item)">+</button> </td> <td> {{ item.price * item.nums }} </td> <td> <button @click="del(index)">删除</button> </td> </tr> </tbody> <tfoot> <tr> <td> 全选 <input type="checkbox" :checked="isallCheck" @click="allcheck"> </td> <td colspan="5" style="text-align: right;"> 共 <span>{{allnum}} </span> 件商品,共计 <span>{{ allprice.toFixed(2) }}</span> 元 <button>立即结算</button> </td> </tr> </tfoot> </table> </body> <script> let vm = new Vue({ el:"#app", data :{ allnum:0, allprice:0, isallCheck:false, arr:[ { title:"苹果6", price:2000, nums:1 }, { title:"华为p30", price:4000, nums:1 }, { title:"vivo X9", price:3000, nums:1 }, { title:"oppro R9", price:3000, nums:1 } ] }, created:function(){ console.log("自己执行啊"); }, watch:{ arr:{ deep:true, handler(){ // 判断是否全选,如果list中每一个都是true那么就全选 let state = true; // 全选状态 let allnum = 0; let allprice =0 ; this.arr.map(val=>{ if(!val.check){ // 没有选中 state = false; }else{ // 选中 allnum++; allprice += (val.nums*val.price) } }) if(!this.arr.length){ state = false; } this.isallCheck = state; this.allnum = allnum; this.allprice = allprice; } } }, methods:{ add(row){ // 添加 row.nums++ row.check = true; }, reduce(row){ // 减少 if(row.nums==1){ return; } row.nums--; row.check = true; }, allcheck(ev){ // 全选 this.isallCheck = ev.target.checked this.arr = this.arr.map(val=>{ val.check = ev.target.checked; return val; }); }, rowCheck(row,ev){ // 单选 row.check = ev.target.checked; }, del(idx){ this.arr.splice(idx,1) } } }) // 直接修改data中的数组 vm.arr = vm.arr.map(val=>{ vm.$set(val,'check',false) return val; }) // 希望页面已进入 data中的arr中的每个都加上一个check属性。而不是依赖于计算属性实现。 // let newarr = arr.map(function(val,key){ return val+1 }) // 遍历 arr每个数据都加1,返回一个新数组 </script> </html>
2、表单知识
2.1、核心指令 v-model
-
所有控件添加上 v-model指令绑定一个变量
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> </head> <body> <div id="app"> <!-- <input type="text" @keyup="change">{{nums}} --> <input type="text" v-model="nums" >{{nums}} </div> </body> <script> // new Vue({ // el:"#app", // data:{ // nums:200 // }, // methods:{ // change(ev){ // console.log(ev.target.value); // this.nums = ev.target.value // } // } // }) new Vue({ el:"#app", data:{ nums:200 } }) // 表单 双向数据绑定!!! // 核心指令 v-model </script> </html>
-
不同的控件绑定稍微有所不同
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> </head> <body> <div id="app"> 姓名: <input type="text" v-model="xm" >{{xm}} <br> 性别: <label for=""><input type="radio" v-model="sex" value="1">男</label> <label for=""><input type="radio" v-model="sex" value="0">女</label> {{sex}} <br> 爱好: <label for=""><input v-model="ah" value="lq" type="checkbox">篮球</label> <label for=""><input v-model="ah" value="zq" type="checkbox">足球</label> <label for=""><input v-model="ah" value="ymq" type="checkbox">羽毛球</label> <label for=""><input v-model="ah" value="pq" type="checkbox">皮球</label> {{ah}} <br> 是否成年:<input type="checkbox" v-model="cn">{{cn}} <br> 家乡: <select v-model="jx"> <option value="0">请选择</option> <option value="bj">北京</option> <option value="nj">南京</option> <option value="tj">天津</option> <option value="hf">合肥</option> </select> {{jx}} <br> 想去的地方: <select v-model="ly" multiple size="5"> <option value="dj">东京</option> <option value="ny">纽约</option> <option value="ld">伦敦</option> <option value="ylk">伊拉克</option> </select> {{ly}} <br> 想说的话: <textarea v-model="text" cols="30" rows="5"></textarea>{{text}} <br> <button>提交</button> </div> </body> <script> new Vue({ el:"#app", data:{ xm:"张飞", sex:"1", ah:['ymq','lq'], cn:false, jx:"tj", ly:['ny','ylk'], text:"" } }) // 表单 双向数据绑定!!! // 核心指令 v-model // 文本框、密码框、多行文本输入框 v-model 的变量 直接和 控件的value进行绑定,不需要描述value // 单选框 同一组单选 v-model绑定相同变量 该变量是个具体的值 且每个单选项需要指定value值, value值和v-model绑定的变量值相同的话,该控件被选中 // 多选框 多选 同一组多选 v-model绑定相同变量 该变量数个数组 且每个多选项需要指定value值, value值和v-model绑定的数组变量值里面的值相同的话,该控件被选中 // 多选框 勾中 v-model绑定一个布尔变量 无需指定value, 自动获取true或者false // 下拉框: // 单选 v-model 绑定一个变量 如果option有value,那么v-model绑定的变量将获取value的值,如果没有value那么将获取option标签之间的文本。 // 多选 v-model 绑定一个数组变量 如果数组中有值,那么对应的option将会被选中,如果没有值,将会去对应的option的value或者标签之间的内容 // 注意: 单选 和 多选 需要每个控件项都需要有对应的value </script> </html>
2.2、表单修饰符
-
修饰符,帮助我们对绑定的数据进行一些处理。 将字符串变成数字,去除两端的空格等等
-
使用:
<input type="text" v-model.修饰符="变量" />
-
那些修饰符?
-
number v-model.number = “变量” 将字符串变成数字
-
trim v-model.trim=“变量” 去除两端的空格
-
lazy v-model.lazy=“变量” 在“change”时触发更新 而非“input”时更新
-
3、生命周期
3.1、又称生命周期钩子
3.2、掌握内容
-
有哪些阶段
-
该阶段有哪些函数
-
该阶段我们能获取到Vue实例里面什么东西
-
该阶段我们在工作用一般干什么
3.3、四个阶段
-
创建阶段
- 创建之前: beforeCreate 一进入就要做得事情, 但是这里无法获取data,也没有挂载
- 创建之后:created 数据请求 可以访问data了,也没挂载
-
挂载阶段
- 挂载之前:beforeMount 挂载之前要做的事 可以访问data,没挂载成功了
- 挂载之后:mounted 去初始化一些外部插件 可以访问data,挂载成功了
-
更新阶段
- 更新之前:beforeUpdate 判断是否要更新 刷新判断 可以访问data,挂载成功
- 更新之后:updated 更新之后要做的事情 可以访问data,挂载成功的
-
消亡阶段
-
消亡之前:beforeDestroy 判断是否保存 可以访问data,挂载成功
-
消亡之后: destroyed 清楚变量、定时器、 等等
-
3.4、生命周期图
4、学生信息案例
4.1、 技术点内容
- 本地存储
- 跨页面之间传值
- 增删改查
- Vue绑定数据
- Vue数据渲染
4.2、代码
-
添加页面
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>添加</title> <link href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css" rel="stylesheet"> <style> .form-control{ width: 75%; } </style> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> </head> <body> <div class="container" id="app"> <h3 class="text-center "><a class="btn btn-success pull-left" href="javascript:history.go(-1);"><返回</a> 添加学生记录</h3> <hr> <div class="row"> <div class="col-md-6 col-md-offset-3"> <form class="form-horizontal"> <div class="form-group"> <label for="" class="col-md-3 control-label">姓名</label> <input type="text" v-model.trim="userInfo.username" class="col-md-9 form-control "> </div> <div class="form-group"> <label for="" class="col-md-3 control-label">密码</label> <input type="password" v-model.trim="userInfo.password" class="col-md-9 form-control "> </div> <div class="form-group"> <label for="" class="col-md-3 control-label">性别</label> <div class="radio"> <label> <input type="radio" v-model.number="userInfo.sex" value="1" >男 </label> <label> <input type="radio" v-model.number="userInfo.sex" value="0" >女 </label> </div> </div> <div class="form-group"> <label for="" class="col-md-3 control-label">爱好</label> <div class="checkbox"> <label><input type="checkbox" v-model="userInfo.ah" value="篮球">篮球</label> <label><input type="checkbox" v-model="userInfo.ah" value="足球">足球</label> <label><input type="checkbox" v-model="userInfo.ah" value="羽毛球">羽毛球</label> <label><input type="checkbox" v-model="userInfo.ah" value="排球">排球</label> </div> </div> <div class="form-group"> <label for="" class="col-md-3 control-label">是否成年</label> <div class="checkbox"> <label><input type="checkbox" v-model="userInfo.isdr" >成年请勾选</label> </div> </div> <div class="form-group"> <label for="" class="col-md-3 control-label">家乡</label> <select class="col-md-9 form-control " v-model="userInfo.from"> <option value="0">---请选择---</option> <option>北京</option> <option>天津</option> <option>南京</option> </select> </div> <div class="form-group"> <label for="" class="col-md-3 control-label">想去的城市</label> <select v-model="userInfo.city" multiple class="col-md-9 form-control "> <option >东京</option> <option >纽约</option> <option >伦敦</option> <option>伊拉克</option> </select> </div> <div class="form-group"> <label for="" class="col-md-3 control-label">个性签名</label> <textarea v-model="userInfo.desc" class="form-control" rows="3"></textarea> </div> <button type="submit" @click.prevent="add" class="btn btn-primary col-md-offset-3" >添加</button> </form> </div> </div> </div> </body> <script> new Vue({ el:"#app", data:{ userInfo:{ username:"", password:"", sex:1, ah:[], isdr:false, from:0, city:[], desc:"" } }, methods:{ add(){ if(!this.userInfo.username || !this.userInfo.password){ alert("至少输入姓名和密码"); return; } let data = localStorage.getItem("studentData"); if(data){ // 不是第一次 console.log(data); data = JSON.parse(data); // 原来的数据 data.push(this.userInfo); }else{ //第一次 data = [this.userInfo]; } localStorage.setItem('studentData',JSON.stringify(data)); // window.location.reload(); window.location.href = "list.html" } } }) </script> </html>
-
列表页面
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>学生信息记录</title> <link href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css" rel="stylesheet"> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> </head> <body> <div class="container" id="app"> <h3 class="text-center">学生信息记录 <a href="add.html" class="btn btn-success pull-right">添加记录</a></h3> <hr> <br> <table class="table table-bordered"> <thead> <th>姓名</th> <th>密码</th> <th>性别</th> <th>是否成年</th> <th>爱好</th> <th>家乡</th> <th>操作</th> </thead> <tbody> <template v-if="list.length"> <tr v-for="(item,index) in list"> <td>{{item.username}}</td> <td>{{item.password}}</td> <td>{{ item.sex ? '男':'女' }}</td> <td>{{ item.isdr ? "成年" : "小孩" }}</td> <td>{{ item.ah.join(",") }}</td> <td>{{ item.from ? item.from : '来自远方' }}</td> <td> <button @click="go(index,'info')" class="btn-success">查看</button> <button @click="go(index,'edit')" class="btn-primary">修改</button> <button @click="del(index)" class="btn-danger">删除</button> </td> </tr> </template> <template v-else> <tr> <td colspan="7" class="text-center">没有数据</td> </tr> </template> </tbody> </table> </div> </body> <script> new Vue({ el:"#app", data:{ list:[] }, created(){ if(localStorage.getItem("studentData")){ this.list = JSON.parse( localStorage.getItem("studentData") ); } }, methods:{ del(idx){// 删除 if(!window.confirm("是否要删除")){ return; } this.list.splice(idx,1); // 删除页面 let localList = JSON.parse( localStorage.getItem("studentData") ); localList.splice(idx,1); // 删除本地 localStorage.setItem("studentData",JSON.stringify(localList)); // 放回去 }, go(idx,str){ // 查看 location.href = str+".html?id="+idx; } } }) </script> </html>
-
删除功能
- 见列表页面
-
修改功能(添加逻辑一致)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>修改</title> <link href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css" rel="stylesheet"> <style> .form-control{ width: 75%; } </style> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> </head> <body> <div class="container" id="app"> <h3 class="text-center "><a class="btn btn-success pull-left" href="javascript:history.go(-1);"><返回</a> 修改学生记录</h3> <hr> <div class="row"> <div class="col-md-6 col-md-offset-3"> <form class="form-horizontal"> <div class="form-group"> <label for="" class="col-md-3 control-label">姓名</label> <input type="text" v-model.trim="userInfo.username" class="col-md-9 form-control "> </div> <div class="form-group"> <label for="" class="col-md-3 control-label">密码</label> <input type="password" v-model.trim="userInfo.password" class="col-md-9 form-control "> </div> <div class="form-group"> <label for="" class="col-md-3 control-label">性别</label> <div class="radio"> <label> <input type="radio" v-model.number="userInfo.sex" value="1" >男 </label> <label> <input type="radio" v-model.number="userInfo.sex" value="0" >女 </label> </div> </div> <div class="form-group"> <label for="" class="col-md-3 control-label">爱好</label> <div class="checkbox"> <label><input type="checkbox" v-model="userInfo.ah" value="篮球">篮球</label> <label><input type="checkbox" v-model="userInfo.ah" value="足球">足球</label> <label><input type="checkbox" v-model="userInfo.ah" value="羽毛球">羽毛球</label> <label><input type="checkbox" v-model="userInfo.ah" value="排球">排球</label> </div> </div> <div class="form-group"> <label for="" class="col-md-3 control-label">是否成年</label> <div class="checkbox"> <label><input type="checkbox" v-model="userInfo.isdr" >成年请勾选</label> </div> </div> <div class="form-group"> <label for="" class="col-md-3 control-label">家乡</label> <select class="col-md-9 form-control " v-model="userInfo.from"> <option value="0">---请选择---</option> <option>北京</option> <option>天津</option> <option>南京</option> </select> </div> <div class="form-group"> <label for="" class="col-md-3 control-label">想去的城市</label> <select v-model="userInfo.city" multiple class="col-md-9 form-control "> <option >东京</option> <option >纽约</option> <option >伦敦</option> <option>伊拉克</option> </select> </div> <div class="form-group"> <label for="" class="col-md-3 control-label">个性签名</label> <textarea v-model="userInfo.desc" class="form-control" rows="3"></textarea> </div> <button type="submit" @click.prevent="eidt" class="btn btn-danger col-md-offset-3" >修改</button> </form> </div> </div> </div> </body> <script> new Vue({ el:"#app", data:{ userInfo:{ username:"", password:"", sex:1, ah:[], isdr:false, from:0, city:[], desc:"" }, idx:"" }, created(){ let id = location.search.split("=")[1] this.idx = id; let studentData = localStorage.getItem("studentData"); studentData = JSON.parse(studentData); this.userInfo = studentData[id]; }, methods:{ eidt(){ if(!this.userInfo.username || !this.userInfo.password){ alert("至少输入姓名和密码"); return; } let data = localStorage.getItem("studentData");// 本地的学生数据 data = JSON.parse(data); data[this.idx] = this.userInfo localStorage.setItem('studentData',JSON.stringify(data)); window.location.href = "list.html" } } }) </script> </html>
-
详情页面
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>学生信息详情</title> <link href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css" rel="stylesheet"> <style> .form-control { width: 75%; } </style> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> </head> <body> <div class="container" id="app"> <h3 class="text-center "> 学生信息 <a class="btn btn-success pull-left" href="javascript:history.go(-1);"><返回</a> </h3> <hr> <div class="row"> <div class="col-md-6 col-md-offset-3"> <form class="form-horizontal"> <div class="form-group"> <label for="" class="col-md-3 control-label">姓名</label> <input type="text" readonly v-model="userInfo.username" class="col-md-9 form-control "> </div> <div class="form-group"> <label for="" class="col-md-3 control-label">密码</label> <input type="password" readonly v-model="userInfo.password" class="col-md-9 form-control "> </div> <div class="form-group"> <label for="" class="col-md-3 control-label">性别</label> <div class="radio"> {{ userInfo.sex ? "男":"女" }} </div> </div> <div class="form-group"> <label for="" class="col-md-3 control-label">爱好</label> <div class="checkbox"> {{ userInfo.ah.join(",")}} </div> </div> <div class="form-group"> <label for="" class="col-md-3 control-label">是否成年</label> <div class="checkbox"> {{ userInfo.isdr ? "成年":"小孩" }} </div> </div> <div class="form-group"> <label for="" class="col-md-3 control-label">家乡</label> {{userInfo.from ? userInfo.from : "来自远方"}} </div> <div class="form-group"> <label for="" class="col-md-3 control-label">想去的城市</label> {{userInfo.city.join(",")}} </div> <div class="form-group"> <label for="" class="col-md-3 control-label">个性签名</label> <textarea readonly v-model="userInfo.desc" class="form-control" rows="3"></textarea> </div> </form> </div> </div> </div> </body> <script> new Vue({ el: "#app", data: { userInfo: { username: "", password: "", sex: "1", ah: [], isdr: false, from: "", city: [], desc: "" } }, created(){ let id = location.search.split("=")[1] let studentData = localStorage.getItem("studentData"); studentData = JSON.parse(studentData); this.userInfo = studentData[id]; } }) </script> </html>