seo网站程序,设计网有哪些,阿坝网页设计公司,wordpress 仿头条主题文章目录 前言一、指令补充1. 指令修饰符2. v-bind对于样式操作的增强 - class3. 案例 - 京东秒杀 tab 导航高亮4. v-bind对于样式操作的增强 - style5. v-model应用于其他表单元素 二、computed计算属性1. 基础语法2. 计算属性 vS method 方法3. 完整写法4. 成绩案例 三、watc… 文章目录 前言一、指令补充1. 指令修饰符2. v-bind对于样式操作的增强 - class3. 案例 - 京东秒杀 tab 导航高亮4. v-bind对于样式操作的增强 - style5. v-model应用于其他表单元素 二、computed计算属性1. 基础语法2. 计算属性 vS method 方法3. 完整写法4. 成绩案例 三、watch 侦听器1. 基础语法2. 业务实现3. 完整写法 四、综合案例:水果购物车1. 渲染2. 删除和修改数量3. 全选反选4. 统计总价5. 本地持久化 总结 前言
为了巩固所学的知识作者尝试着开始发布一些学习笔记类的博客方便日后回顾。当然如果能帮到一些萌新进行新技术的学习那也是极好的。作者菜菜一枚文章中如果有记录错误欢迎读者朋友们批评指正。
一、指令补充
1. 指令修饰符 keyup.enter
!DOCTYPE html
html langen
headmeta charsetUTF-8meta http-equivX-UA-Compatible contentIEedgemeta nameviewport contentwidthdevice-width, initial-scale1.0titleDocument/title
/head
bodydiv idapph3keyup.enter → 监听键盘回车事件/h3input keyup.enterfn v-modelusername typetext/divscript srchttps://cdn.jsdelivr.net/npm/vue2/dist/vue.js/scriptscriptconst app new Vue({el: #app,data: {username: },methods: {fn (e) {// if (e.key Enter) {// console.log(键盘回车的时候触发, this.username)// }console.log(键盘回车的时候触发, this.username)}}})/script
/body
/html.trim .number .stop .prevent
!DOCTYPE html
html langen
headmeta charsetUTF-8meta http-equivX-UA-Compatible contentIEedgemeta nameviewport contentwidthdevice-width, initial-scale1.0titleDocument/titlestyle.father {width: 200px;height: 200px;background-color: pink;margin-top: 20px;}.son {width: 100px;height: 100px;background-color: skyblue;}/style
/head
bodydiv idapph3v-model修饰符 .trim .number/h3姓名input v-model.trimusername typetextbr年纪input v-model.numberage typetextbrh3事件名.stop → 阻止冒泡/h3div clickfatherFn classfatherdiv click.stopsonFn classson儿子/div/divh3事件名.prevent → 阻止默认行为/h3a click.prevent hrefhttp://www.baidu.com阻止默认行为/a/divscript srchttps://cdn.jsdelivr.net/npm/vue2/dist/vue.js/scriptscriptconst app new Vue({el: #app,data: {username: ,age: ,},methods: {fatherFn () {alert(老父亲被点击了)},sonFn (e) {// e.stopPropagation()alert(儿子被点击了)}}})/script
/body
/html2. v-bind对于样式操作的增强 - class !DOCTYPE html
html langen
headmeta charsetUTF-8meta http-equivX-UA-Compatible contentIEedgemeta nameviewport contentwidthdevice-width, initial-scale1.0titleDocument/titlestyle.box {width: 200px;height: 200px;border: 3px solid #000;font-size: 30px;margin-top: 10px;}.pink {background-color: pink;}.big {width: 300px;height: 300px;}/style
/head
bodydiv idappdiv classbox :class{ pink: true, big: true }黑马程序员/divdiv classbox :class[pink, big]黑马程序员/div/divscript srchttps://cdn.jsdelivr.net/npm/vue2/dist/vue.js/scriptscriptconst app new Vue({el: #app,data: {}})/script
/body
/html3. 案例 - 京东秒杀 tab 导航高亮 !DOCTYPE html
html langen
headmeta charsetUTF-8meta http-equivX-UA-Compatible contentIEedgemeta nameviewport contentwidthdevice-width, initial-scale1.0titleDocument/titlestyle* {margin: 0;padding: 0;}ul {display: flex;border-bottom: 2px solid #e01222;padding: 0 10px;}li {width: 100px;height: 50px;line-height: 50px;list-style: none;text-align: center;}li a {display: block;text-decoration: none;font-weight: bold;color: #333333;}li a.active {background-color: #e01222;color: #fff;}/style
/head
bodydiv idappulli v-for(item, index) in list :keyitem.id clickactiveIndex indexa :class{ active: index activeIndex } href#{{ item.name }}/a/li/ul/divscript srchttps://cdn.jsdelivr.net/npm/vue2/dist/vue.js/scriptscriptconst app new Vue({el: #app,data: {activeIndex: 2, // 记录高亮list: [{ id: 1, name: 京东秒杀 },{ id: 2, name: 每日特价 },{ id: 3, name: 品类秒杀 }]}})/script
/body
/html4. v-bind对于样式操作的增强 - style !DOCTYPE html
html langen
headmeta charsetUTF-8meta http-equivX-UA-Compatible contentIEedgemeta nameviewport contentwidthdevice-width, initial-scale1.0titleDocument/titlestyle.progress {height: 25px;width: 400px;border-radius: 15px;background-color: #272425;border: 3px solid #272425;box-sizing: border-box;margin-bottom: 30px;}.inner {width: 50%;height: 20px;border-radius: 10px;text-align: right;position: relative;background-color: #409eff;background-size: 20px 20px;box-sizing: border-box;transition: all 1s;}.inner span {position: absolute;right: -20px;bottom: -25px;}/style
/head
bodydiv idapp!-- 外层盒子底色 黑色 --div classprogress!-- 内层盒子 - 进度蓝色 --div classinner :style{ width: percent % }span{{ percent }}%/span/div/divbutton clickpercent 25设置25%/buttonbutton clickpercent 50设置50%/buttonbutton clickpercent 75设置75%/buttonbutton clickpercent 100设置100%/button/divscript srchttps://cdn.jsdelivr.net/npm/vue2/dist/vue.js/scriptscriptconst app new Vue({el: #app,data: {percent: 30}})/script
/body
/html5. v-model应用于其他表单元素 !DOCTYPE html
html langen
headmeta charsetUTF-8meta http-equivX-UA-Compatible contentIEedgemeta nameviewport contentwidthdevice-width, initial-scale1.0titleDocument/titlestyletextarea {display: block;width: 240px;height: 100px;margin: 10px 0;}/style
/head
bodydiv idapph3小黑学习网/h3姓名input typetext v-modelusername brbr是否单身input typecheckbox v-modelisSingle brbr!-- 前置理解1. name: 给单选框加上 name 属性 可以分组 → 同一组互相会互斥2. value: 给单选框加上 value 属性用于提交给后台的数据结合 Vue 使用 → v-model--性别: input v-modelgender typeradio namegender value1男input v-modelgender typeradio namegender value2女brbr!-- 前置理解1. option 需要设置 value 值提交给后台2. select 的 value 值关联了选中的 option 的 value 值结合 Vue 使用 → v-model--所在城市:select v-modelcityIdoption value101北京/optionoption value102上海/optionoption value103成都/optionoption value104南京/option/selectbrbr自我描述textarea v-modeldesc/textarea button立即注册/button/divscript srchttps://cdn.jsdelivr.net/npm/vue2/dist/vue.js/scriptscriptconst app new Vue({el: #app,data: {username: ,isSingle: false,gender: 2,cityId: 102,desc: }})/script
/body
/html二、computed计算属性
1. 基础语法 !DOCTYPE html
html langen
headmeta charsetUTF-8meta http-equivX-UA-Compatible contentIEedgemeta nameviewport contentwidthdevice-width, initial-scale1.0titleDocument/titlestyletable {border: 1px solid #000;text-align: center;width: 240px;}th,td {border: 1px solid #000;}h3 {position: relative;}/style
/head
bodydiv idapph3小黑的礼物清单/h3tabletrth名字/thth数量/th/trtr v-for(item, index) in list :keyitem.idtd{{ item.name }}/tdtd{{ item.num }}个/td/tr/table!-- 目标统计求和求得礼物总数 --p礼物总数{{ totalCount }} 个/p/divscript srchttps://cdn.jsdelivr.net/npm/vue2/dist/vue.js/scriptscriptconst app new Vue({el: #app,data: {// 现有的数据list: [{ id: 1, name: 篮球, num: 1 },{ id: 2, name: 玩具, num: 2 },{ id: 3, name: 铅笔, num: 5 },]},computed: {totalCount () {// 基于现有的数据编写求值逻辑// 计算属性函数内部可以直接通过 this 访问到 app 实例// console.log(this.list)// 需求对 this.list 数组里面的 num 进行求和 → reducelet total this.list.reduce((sum, item) sum item.num, 0)return total}}})/script
/body
/html2. 计算属性 vS method 方法 !DOCTYPE html
html langen
headmeta charsetUTF-8meta http-equivX-UA-Compatible contentIEedgemeta nameviewport contentwidthdevice-width, initial-scale1.0titleDocument/titlestyletable {border: 1px solid #000;text-align: center;width: 300px;}th,td {border: 1px solid #000;}h3 {position: relative;}span {position: absolute;left: 145px;top: -4px;width: 16px;height: 16px;color: white;font-size: 12px;text-align: center;border-radius: 50%;background-color: #e63f32;}/style
/head
bodydiv idapph3小黑的礼物清单span{{ totalCountFn() }}/span/h3h3小黑的礼物清单span{{ totalCountFn() }}/span/h3h3小黑的礼物清单span{{ totalCountFn() }}/span/h3h3小黑的礼物清单span{{ totalCountFn() }}/span/h3tabletrth名字/thth数量/th/trtr v-for(item, index) in list :keyitem.idtd{{ item.name }}/tdtd{{ item.num }}个/td/tr/tablep礼物总数{{ totalCountFn() }} 个/p/divscript srchttps://cdn.jsdelivr.net/npm/vue2/dist/vue.js/scriptscriptconst app new Vue({el: #app,data: {// 现有的数据list: [{ id: 1, name: 篮球, num: 3 },{ id: 2, name: 玩具, num: 2 },{ id: 3, name: 铅笔, num: 5 },]},methods: {totalCountFn () {console.log(methods方法执行了)let total this.list.reduce((sum, item) sum item.num, 0)return total}},computed: {// 计算属性有缓存的一旦计算出来结果就会立刻缓存// 下一次读取 → 直接读缓存就行 → 性能特别高// totalCount () {// console.log(计算属性执行了)// let total this.list.reduce((sum, item) sum item.num, 0)// return total// }}})/script
/body
/html3. 完整写法 !DOCTYPE html
html langen
headmeta charsetUTF-8meta http-equivX-UA-Compatible contentIEedgemeta nameviewport contentwidthdevice-width, initial-scale1.0titleDocument/titlestyleinput {width: 30px;}/style
/head
bodydiv idapp姓input typetext v-modelfirstName 名input typetext v-modellastName span{{ fullName }}/spanbrbrbutton clickchangeName改名卡/button/divscript srchttps://cdn.jsdelivr.net/npm/vue2/dist/vue.js/scriptscriptconst app new Vue({el: #app,data: {firstName: 刘,lastName: 备,},methods: {changeName () {this.fullName 黄忠}},computed: {// 简写 → 获取没有配置设置的逻辑// fullName () {// return this.firstName this.lastName// }// 完整写法 → 获取 设置fullName: {// (1) 当fullName计算属性被获取求值时执行get有缓存优先读缓存// 会将返回值作为求值的结果get () {return this.firstName this.lastName},// (2) 当fullName计算属性被修改赋值时执行set// 修改的值传递给set方法的形参set (value) {// console.log(value.slice(0, 1)) // console.log(value.slice(1)) this.firstName value.slice(0, 1)this.lastName value.slice(1)}}}})/script
/body
/html4. 成绩案例 渲染实现
!DOCTYPE html
html langenheadmeta charsetUTF-8 /meta http-equivX-UA-Compatible contentIEedge /meta nameviewport contentwidthdevice-width, initial-scale1.0 /link relstylesheet href./styles/index.css /titleDocument/title/headbodydiv idapp classscore-casediv classtabletabletheadtrth编号/thth科目/thth成绩/thth操作/th/tr/theadtbody v-iflist.length 0tr v-for(item, index) in list :keyitem.idtd{{ index 1 }}/tdtd{{ item.subject }}/td!-- 需求不及格的标红, 60 分, 加上 red 类 --td :class{ red: item.score 60 }{{ item.score }}/tdtda href#删除/a/td/tr/tbodytbody v-elsetrtd colspan5span classnone暂无数据/span/td/tr/tbodytfoottrtd colspan5span总分246/spanspan stylemargin-left: 50px平均分79/span/td/tr/tfoot/table/divdiv classformdiv classform-itemdiv classlabel科目/divdiv classinputinputtypetextplaceholder请输入科目//div/divdiv classform-itemdiv classlabel分数/divdiv classinputinputtypetextplaceholder请输入分数//div/divdiv classform-itemdiv classlabel/divdiv classinputbutton classsubmit 添加/button/div/div/div/divscript srchttps://cdn.jsdelivr.net/npm/vue2/dist/vue.js/scriptscriptconst app new Vue({el: #app,data: {list: [{ id: 1, subject: 语文, score: 62 },{ id: 7, subject: 数学, score: 39 },{ id: 12, subject: 英语, score: 70 },],subject: ,score: }})/script/body
/html
添加删除
!DOCTYPE html
html langenheadmeta charsetUTF-8 /meta http-equivX-UA-Compatible contentIEedge /meta nameviewport contentwidthdevice-width, initial-scale1.0 /link relstylesheet href./styles/index.css /titleDocument/title/headbodydiv idapp classscore-casediv classtabletabletheadtrth编号/thth科目/thth成绩/thth操作/th/tr/theadtbody v-iflist.length 0tr v-for(item, index) in list :keyitem.idtd{{ index 1 }}/tdtd{{ item.subject }}/td!-- 需求不及格的标红, 60 分, 加上 red 类 --td :class{ red: item.score 60 }{{ item.score }}/tdtda click.preventdel(item.id) hrefhttp://www.baidu.com删除/a/td/tr/tbodytbody v-elsetrtd colspan5span classnone暂无数据/span/td/tr/tbodytfoottrtd colspan5span总分246/spanspan stylemargin-left: 50px平均分79/span/td/tr/tfoot/table/divdiv classformdiv classform-itemdiv classlabel科目/divdiv classinputinputtypetextplaceholder请输入科目v-model.trimsubject//div/divdiv classform-itemdiv classlabel分数/divdiv classinputinputtypetextplaceholder请输入分数v-model.numberscore//div/divdiv classform-itemdiv classlabel/divdiv classinputbutton clickadd classsubmit 添加/button/div/div/div/divscript srchttps://cdn.jsdelivr.net/npm/vue2/dist/vue.js/scriptscriptconst app new Vue({el: #app,data: {list: [{ id: 1, subject: 语文, score: 62 },{ id: 7, subject: 数学, score: 39 },{ id: 12, subject: 英语, score: 70 },],subject: ,score: },methods: {del (id) {// console.log(id)this.list this.list.filter(item item.id ! id)},add () {if (!this.subject) {alert(请输入科目)return}if (typeof this.score ! number) {alert(请输入正确的成绩)return}this.list.unshift({id: new Date(),subject: this.subject,score: this.score})this.subject this.score }}})/script/body
/html
计算属性
!DOCTYPE html
html langenheadmeta charsetUTF-8 /meta http-equivX-UA-Compatible contentIEedge /meta nameviewport contentwidthdevice-width, initial-scale1.0 /link relstylesheet href./styles/index.css /titleDocument/title/headbodydiv idapp classscore-casediv classtabletabletheadtrth编号/thth科目/thth成绩/thth操作/th/tr/theadtbody v-iflist.length 0tr v-for(item, index) in list :keyitem.idtd{{ index 1 }}/tdtd{{ item.subject }}/td!-- 需求不及格的标红, 60 分, 加上 red 类 --td :class{ red: item.score 60 }{{ item.score }}/tdtda click.preventdel(item.id) hrefhttp://www.baidu.com删除/a/td/tr/tbodytbody v-elsetrtd colspan5span classnone暂无数据/span/td/tr/tbodytfoottrtd colspan5span总分{{ totalScore }}/spanspan stylemargin-left: 50px平均分{{ averageScore }}/span/td/tr/tfoot/table/divdiv classformdiv classform-itemdiv classlabel科目/divdiv classinputinputtypetextplaceholder请输入科目v-model.trimsubject//div/divdiv classform-itemdiv classlabel分数/divdiv classinputinputtypetextplaceholder请输入分数v-model.numberscore//div/divdiv classform-itemdiv classlabel/divdiv classinputbutton clickadd classsubmit 添加/button/div/div/div/divscript srchttps://cdn.jsdelivr.net/npm/vue2/dist/vue.js/scriptscriptconst app new Vue({el: #app,data: {list: [{ id: 1, subject: 语文, score: 62 },{ id: 7, subject: 数学, score: 89 },{ id: 12, subject: 英语, score: 70 },],subject: ,score: },computed: {totalScore() {return this.list.reduce((sum, item) sum item.score, 0)},averageScore () {if (this.list.length 0) {return 0}return (this.totalScore / this.list.length).toFixed(2)}},methods: {del (id) {// console.log(id)this.list this.list.filter(item item.id ! id)},add () {if (!this.subject) {alert(请输入科目)return}if (typeof this.score ! number) {alert(请输入正确的成绩)return}this.list.unshift({id: new Date(),subject: this.subject,score: this.score})this.subject this.score }}})/script/body
/html 三、watch 侦听器
1. 基础语法 !DOCTYPE html
html langenheadmeta charsetUTF-8 /meta http-equivX-UA-Compatible contentIEedge /meta nameviewport contentwidthdevice-width, initial-scale1.0 /titleDocument/titlestyle* {margin: 0;padding: 0;box-sizing: border-box;font-size: 18px;}#app {padding: 10px 20px;}.query {margin: 10px 0;}.box {display: flex;}textarea {width: 300px;height: 160px;font-size: 18px;border: 1px solid #dedede;outline: none;resize: none;padding: 10px;}textarea:hover {border: 1px solid #1589f5;}.transbox {width: 300px;height: 160px;background-color: #f0f0f0;padding: 10px;border: none;}.tip-box {width: 300px;height: 25px;line-height: 25px;display: flex;}.tip-box span {flex: 1;text-align: center;}.query span {font-size: 18px;}.input-wrap {position: relative;}.input-wrap span {position: absolute;right: 15px;bottom: 15px;font-size: 12px;}.input-wrap i {font-size: 20px;font-style: normal;}/style/headbodydiv idapp!-- 条件选择框 --div classqueryspan翻译成的语言/spanselectoption valueitaly意大利/optionoption valueenglish英语/optionoption valuegerman德语/option/select/div!-- 翻译框 --div classboxdiv classinput-wraptextarea v-modelobj.words/textareaspani⌨️/i文档翻译/span/divdiv classoutput-wrapdiv classtransboxmela/div/div/div/divscript srchttps://cdn.jsdelivr.net/npm/vue2/dist/vue.js/scriptscript srchttps://cdn.jsdelivr.net/npm/axios/dist/axios.min.js/scriptscript// 接口地址https://applet-base-api-t.itheima.net/api/translate// 请求方式get// 请求参数// 1words需要被翻译的文本必传// 2lang 需要被翻译成的语言可选默认值-意大利// -----------------------------------------------const app new Vue({el: #app,data: {// words: obj: {words: }},// 具体讲解(1) watch语法 (2) 具体业务实现watch: {// 该方法会在数据变化时调用执行// newValue新值, oldValue老值一般不用// words (newValue) {// console.log(变化了, newValue)// }obj.words (newValue) {console.log(变化了, newValue)}}})/script/body
/html 2. 业务实现
!DOCTYPE html
html langenheadmeta charsetUTF-8 /meta http-equivX-UA-Compatible contentIEedge /meta nameviewport contentwidthdevice-width, initial-scale1.0 /titleDocument/titlestyle* {margin: 0;padding: 0;box-sizing: border-box;font-size: 18px;}#app {padding: 10px 20px;}.query {margin: 10px 0;}.box {display: flex;}textarea {width: 300px;height: 160px;font-size: 18px;border: 1px solid #dedede;outline: none;resize: none;padding: 10px;}textarea:hover {border: 1px solid #1589f5;}.transbox {width: 300px;height: 160px;background-color: #f0f0f0;padding: 10px;border: none;}.tip-box {width: 300px;height: 25px;line-height: 25px;display: flex;}.tip-box span {flex: 1;text-align: center;}.query span {font-size: 18px;}.input-wrap {position: relative;}.input-wrap span {position: absolute;right: 15px;bottom: 15px;font-size: 12px;}.input-wrap i {font-size: 20px;font-style: normal;}/style/headbodydiv idapp!-- 条件选择框 --div classqueryspan翻译成的语言/spanselectoption valueitaly意大利/optionoption valueenglish英语/optionoption valuegerman德语/option/select/div!-- 翻译框 --div classboxdiv classinput-wraptextarea v-modelobj.words/textareaspani⌨️/i文档翻译/span/divdiv classoutput-wrapdiv classtransbox{{ result }}/div/div/div/divscript srchttps://cdn.jsdelivr.net/npm/vue2/dist/vue.js/scriptscript srchttps://cdn.jsdelivr.net/npm/axios/dist/axios.min.js/scriptscript// 接口地址https://applet-base-api-t.itheima.net/api/translate// 请求方式get// 请求参数// 1words需要被翻译的文本必传// 2lang 需要被翻译成的语言可选默认值-意大利// -----------------------------------------------const app new Vue({el: #app,data: {// words: obj: {words: },result: , // 翻译结果// timer: null // 延时器id},// 具体讲解(1) watch语法 (2) 具体业务实现watch: {// 该方法会在数据变化时调用执行// newValue新值, oldValue老值一般不用// words (newValue) {// console.log(变化了, newValue)// }obj.words (newValue) {// console.log(变化了, newValue)// 防抖: 延迟执行 → 干啥事先等一等延迟一会一段时间内没有再次触发才执行clearTimeout(this.timer)this.timer setTimeout(async () {const res await axios({url: https://applet-base-api-t.itheima.net/api/translate,params: {words: newValue}})this.result res.data.dataconsole.log(res.data.data)}, 300)}}})/script/body
/html 3. 完整写法 !DOCTYPE html
html langenheadmeta charsetUTF-8 /meta http-equivX-UA-Compatible contentIEedge /meta nameviewport contentwidthdevice-width, initial-scale1.0 /titleDocument/titlestyle* {margin: 0;padding: 0;box-sizing: border-box;font-size: 18px;}#app {padding: 10px 20px;}.query {margin: 10px 0;}.box {display: flex;}textarea {width: 300px;height: 160px;font-size: 18px;border: 1px solid #dedede;outline: none;resize: none;padding: 10px;}textarea:hover {border: 1px solid #1589f5;}.transbox {width: 300px;height: 160px;background-color: #f0f0f0;padding: 10px;border: none;}.tip-box {width: 300px;height: 25px;line-height: 25px;display: flex;}.tip-box span {flex: 1;text-align: center;}.query span {font-size: 18px;}.input-wrap {position: relative;}.input-wrap span {position: absolute;right: 15px;bottom: 15px;font-size: 12px;}.input-wrap i {font-size: 20px;font-style: normal;}/style/headbodydiv idapp!-- 条件选择框 --div classqueryspan翻译成的语言/spanselect v-modelobj.langoption valueitaly意大利/optionoption valueenglish英语/optionoption valuegerman德语/option/select/div!-- 翻译框 --div classboxdiv classinput-wraptextarea v-modelobj.words/textareaspani⌨️/i文档翻译/span/divdiv classoutput-wrapdiv classtransbox{{ result }}/div/div/div/divscript srchttps://cdn.jsdelivr.net/npm/vue2/dist/vue.js/scriptscript srchttps://cdn.jsdelivr.net/npm/axios/dist/axios.min.js/scriptscript// 需求输入内容修改语言都实时翻译// 接口地址https://applet-base-api-t.itheima.net/api/translate// 请求方式get// 请求参数// 1words需要被翻译的文本必传// 2lang 需要被翻译成的语言可选默认值-意大利// -----------------------------------------------const app new Vue({el: #app,data: {obj: {words: 小黑,lang: italy},result: , // 翻译结果},watch: {obj: {deep: true, // 深度监视immediate: true, // 立刻执行一进入页面handler就立刻执行一次handler (newValue) {clearTimeout(this.timer)this.timer setTimeout(async () {const res await axios({url: https://applet-base-api-t.itheima.net/api/translate,params: newValue})this.result res.data.dataconsole.log(res.data.data)}, 300)}}// obj.words (newValue) {// clearTimeout(this.timer)// this.timer setTimeout(async () {// const res await axios({// url: https://applet-base-api-t.itheima.net/api/translate,// params: {// words: newValue// }// })// this.result res.data.data// console.log(res.data.data)// }, 300)// }}})/script/body
/html 四、综合案例:水果购物车 1. 渲染
!DOCTYPE html
html langenheadmeta charsetUTF-8 /meta http-equivX-UA-Compatible contentIEedge /meta nameviewport contentwidthdevice-width, initial-scale1.0 /link relstylesheet href./css/inputnumber.css /link relstylesheet href./css/index.css /title购物车/title/headbodydiv classapp-container idapp!-- 顶部banner --div classbanner-boximg srchttp://autumnfish.cn/static/fruit.jpg alt //div!-- 面包屑 --div classbreadcrumbspan/span/span购物车/span/div!-- 购物车主体 --div classmain v-iffruitList.length 0div classtable!-- 头部 --div classtheaddiv classtrdiv classth选中/divdiv classth th-pic图片/divdiv classth单价/divdiv classth num-th个数/divdiv classth小计/divdiv classth操作/div/div/div!-- 身体 --div classtbodydiv v-for(item, index) in fruitList :keyitem.id classtr :class{ active: item.isChecked }div classtdinput typecheckbox v-modelitem.isChecked //divdiv classtdimg :srcitem.icon alt //divdiv classtd{{ item.price }}/divdiv classtddiv classmy-input-numberbutton classdecrease - /buttonspan classmy-input__inner{{ item.num }}/spanbutton classincrease /button/div/divdiv classtd{{ item.num * item.price }}/divdiv classtdbutton删除/button/div/div/div/div!-- 底部 --div classbottom!-- 全选 --label classcheck-allinput typecheckbox /全选/labeldiv classright-box!-- 所有商品总价 --span classprice-box总价nbsp;nbsp;:nbsp;nbsp;¥nbsp;span classprice24/span/span!-- 结算按钮 --button classpay结算( 6 )/button/div/div/div!-- 空车 --div classempty v-else空空如也/div/divscript srchttps://cdn.jsdelivr.net/npm/vue2/dist/vue.js/scriptscriptconst app new Vue({el: #app,data: {// 水果列表fruitList: [{id: 1,icon: http://autumnfish.cn/static/火龙果.png,isChecked: true,num: 2,price: 6,},{id: 2,icon: http://autumnfish.cn/static/荔枝.png,isChecked: false,num: 7,price: 20,},{id: 3,icon: http://autumnfish.cn/static/榴莲.png,isChecked: false,num: 3,price: 40,},{id: 4,icon: http://autumnfish.cn/static/鸭梨.png,isChecked: true,num: 10,price: 3,},{id: 5,icon: http://autumnfish.cn/static/樱桃.png,isChecked: false,num: 20,price: 34,},],},})/script/body
/html
2. 删除和修改数量
!DOCTYPE html
html langenheadmeta charsetUTF-8 /meta http-equivX-UA-Compatible contentIEedge /meta nameviewport contentwidthdevice-width, initial-scale1.0 /link relstylesheet href./css/inputnumber.css /link relstylesheet href./css/index.css /title购物车/title/headbodydiv classapp-container idapp!-- 顶部banner --div classbanner-boximg srchttp://autumnfish.cn/static/fruit.jpg alt //div!-- 面包屑 --div classbreadcrumbspan/span/span购物车/span/div!-- 购物车主体 --div classmain v-iffruitList.length 0div classtable!-- 头部 --div classtheaddiv classtrdiv classth选中/divdiv classth th-pic图片/divdiv classth单价/divdiv classth num-th个数/divdiv classth小计/divdiv classth操作/div/div/div!-- 身体 --div classtbodydiv v-for(item, index) in fruitList :keyitem.id classtr :class{ active: item.isChecked }div classtdinput typecheckbox v-modelitem.isChecked //divdiv classtdimg :srcitem.icon alt //divdiv classtd{{ item.price }}/divdiv classtddiv classmy-input-numberbutton :disableditem.num 1 classdecrease clicksub(item.id) - /buttonspan classmy-input__inner{{ item.num }}/spanbutton classincrease clickadd(item.id) /button/div/divdiv classtd{{ item.num * item.price }}/divdiv classtdbutton clickdel(item.id)删除/button/div/div/div/div!-- 底部 --div classbottom!-- 全选 --label classcheck-allinput typecheckbox /全选/labeldiv classright-box!-- 所有商品总价 --span classprice-box总价nbsp;nbsp;:nbsp;nbsp;¥nbsp;span classprice24/span/span!-- 结算按钮 --button classpay结算( 6 )/button/div/div/div!-- 空车 --div classempty v-else空空如也/div/divscript srchttps://cdn.jsdelivr.net/npm/vue2/dist/vue.js/scriptscriptconst app new Vue({el: #app,data: {// 水果列表fruitList: [{id: 1,icon: http://autumnfish.cn/static/火龙果.png,isChecked: true,num: 2,price: 6,},{id: 2,icon: http://autumnfish.cn/static/荔枝.png,isChecked: false,num: 7,price: 20,},{id: 3,icon: http://autumnfish.cn/static/榴莲.png,isChecked: false,num: 3,price: 40,},{id: 4,icon: http://autumnfish.cn/static/鸭梨.png,isChecked: true,num: 10,price: 3,},{id: 5,icon: http://autumnfish.cn/static/樱桃.png,isChecked: false,num: 20,price: 34,},],},methods: {del (id) {this.fruitList this.fruitList.filter(item item.id ! id)},add (id) {// 1. 根据 id 找到数组中的对应项 → findconst fruit this.fruitList.find(item item.id id)// 2. 操作 num 数量fruit.num},sub (id) {// 1. 根据 id 找到数组中的对应项 → findconst fruit this.fruitList.find(item item.id id)// 2. 操作 num 数量fruit.num--}}})/script/body
/html
3. 全选反选
!DOCTYPE html
html langenheadmeta charsetUTF-8 /meta http-equivX-UA-Compatible contentIEedge /meta nameviewport contentwidthdevice-width, initial-scale1.0 /link relstylesheet href./css/inputnumber.css /link relstylesheet href./css/index.css /title购物车/title/headbodydiv classapp-container idapp!-- 顶部banner --div classbanner-boximg srchttp://autumnfish.cn/static/fruit.jpg alt //div!-- 面包屑 --div classbreadcrumbspan/span/span购物车/span/div!-- 购物车主体 --div classmain v-iffruitList.length 0div classtable!-- 头部 --div classtheaddiv classtrdiv classth选中/divdiv classth th-pic图片/divdiv classth单价/divdiv classth num-th个数/divdiv classth小计/divdiv classth操作/div/div/div!-- 身体 --div classtbodydiv v-for(item, index) in fruitList :keyitem.id classtr :class{ active: item.isChecked }div classtdinput typecheckbox v-modelitem.isChecked //divdiv classtdimg :srcitem.icon alt //divdiv classtd{{ item.price }}/divdiv classtddiv classmy-input-numberbutton :disableditem.num 1 classdecrease clicksub(item.id) - /buttonspan classmy-input__inner{{ item.num }}/spanbutton classincrease clickadd(item.id) /button/div/divdiv classtd{{ item.num * item.price }}/divdiv classtdbutton clickdel(item.id)删除/button/div/div/div/div!-- 底部 --div classbottom!-- 全选 --label classcheck-allinput typecheckbox v-modelisAll/全选/labeldiv classright-box!-- 所有商品总价 --span classprice-box总价nbsp;nbsp;:nbsp;nbsp;¥nbsp;span classprice24/span/span!-- 结算按钮 --button classpay结算( 6 )/button/div/div/div!-- 空车 --div classempty v-else空空如也/div/divscript srchttps://cdn.jsdelivr.net/npm/vue2/dist/vue.js/scriptscriptconst app new Vue({el: #app,data: {// 水果列表fruitList: [{id: 1,icon: http://autumnfish.cn/static/火龙果.png,isChecked: true,num: 2,price: 6,},{id: 2,icon: http://autumnfish.cn/static/荔枝.png,isChecked: false,num: 7,price: 20,},{id: 3,icon: http://autumnfish.cn/static/榴莲.png,isChecked: false,num: 3,price: 40,},{id: 4,icon: http://autumnfish.cn/static/鸭梨.png,isChecked: true,num: 10,price: 3,},{id: 5,icon: http://autumnfish.cn/static/樱桃.png,isChecked: false,num: 20,price: 34,},],},computed: {// 默认计算属性只能获取不能设置要设置需要写完整写法// isAll () {// // 必须所有的小选框都选中全选按钮才选中 → every// return this.fruitList.every(item item.isChecked)// }// 完整写法 get setisAll: {get () {return this.fruitList.every(item item.isChecked)},set (value) {// 基于拿到的布尔值要让所有的小选框 同步状态this.fruitList.forEach(item item.isChecked value)}}},methods: {del (id) {this.fruitList this.fruitList.filter(item item.id ! id)},add (id) {// 1. 根据 id 找到数组中的对应项 → findconst fruit this.fruitList.find(item item.id id)// 2. 操作 num 数量fruit.num},sub (id) {// 1. 根据 id 找到数组中的对应项 → findconst fruit this.fruitList.find(item item.id id)// 2. 操作 num 数量fruit.num--}}})/script/body
/html
4. 统计总价
!DOCTYPE html
html langenheadmeta charsetUTF-8 /meta http-equivX-UA-Compatible contentIEedge /meta nameviewport contentwidthdevice-width, initial-scale1.0 /link relstylesheet href./css/inputnumber.css /link relstylesheet href./css/index.css /title购物车/title/headbodydiv classapp-container idapp!-- 顶部banner --div classbanner-boximg srchttp://autumnfish.cn/static/fruit.jpg alt //div!-- 面包屑 --div classbreadcrumbspan/span/span购物车/span/div!-- 购物车主体 --div classmain v-iffruitList.length 0div classtable!-- 头部 --div classtheaddiv classtrdiv classth选中/divdiv classth th-pic图片/divdiv classth单价/divdiv classth num-th个数/divdiv classth小计/divdiv classth操作/div/div/div!-- 身体 --div classtbodydiv v-for(item, index) in fruitList :keyitem.id classtr :class{ active: item.isChecked }div classtdinput typecheckbox v-modelitem.isChecked //divdiv classtdimg :srcitem.icon alt //divdiv classtd{{ item.price }}/divdiv classtddiv classmy-input-numberbutton :disableditem.num 1 classdecrease clicksub(item.id) - /buttonspan classmy-input__inner{{ item.num }}/spanbutton classincrease clickadd(item.id) /button/div/divdiv classtd{{ item.num * item.price }}/divdiv classtdbutton clickdel(item.id)删除/button/div/div/div/div!-- 底部 --div classbottom!-- 全选 --label classcheck-allinput typecheckbox v-modelisAll/全选/labeldiv classright-box!-- 所有商品总价 --span classprice-box总价nbsp;nbsp;:nbsp;nbsp;¥nbsp;span classprice{{ totalPrice }}/span/span!-- 结算按钮 --button classpay结算( {{ totalCount }} )/button/div/div/div!-- 空车 --div classempty v-else空空如也/div/divscript srchttps://cdn.jsdelivr.net/npm/vue2/dist/vue.js/scriptscriptconst app new Vue({el: #app,data: {// 水果列表fruitList: [{id: 1,icon: http://autumnfish.cn/static/火龙果.png,isChecked: true,num: 2,price: 6,},{id: 2,icon: http://autumnfish.cn/static/荔枝.png,isChecked: false,num: 7,price: 20,},{id: 3,icon: http://autumnfish.cn/static/榴莲.png,isChecked: false,num: 3,price: 40,},{id: 4,icon: http://autumnfish.cn/static/鸭梨.png,isChecked: true,num: 10,price: 3,},{id: 5,icon: http://autumnfish.cn/static/樱桃.png,isChecked: false,num: 20,price: 34,},],},computed: {// 默认计算属性只能获取不能设置要设置需要写完整写法// isAll () {// // 必须所有的小选框都选中全选按钮才选中 → every// return this.fruitList.every(item item.isChecked)// }// 完整写法 get setisAll: {get () {return this.fruitList.every(item item.isChecked)},set (value) {// 基于拿到的布尔值要让所有的小选框 同步状态this.fruitList.forEach(item item.isChecked value)}},// 统计选中的总数 reducetotalCount () {return this.fruitList.reduce((sum, item) {if (item.isChecked) {// 选中 → 需要累加return sum item.num} else {// 没选中 → 不需要累加return sum}}, 0)},// 总计选中的总价 num * pricetotalPrice () {return this.fruitList.reduce((sum, item) {if (item.isChecked) {return sum item.num * item.price} else {return sum}}, 0)}},methods: {del (id) {this.fruitList this.fruitList.filter(item item.id ! id)},add (id) {// 1. 根据 id 找到数组中的对应项 → findconst fruit this.fruitList.find(item item.id id)// 2. 操作 num 数量fruit.num},sub (id) {// 1. 根据 id 找到数组中的对应项 → findconst fruit this.fruitList.find(item item.id id)// 2. 操作 num 数量fruit.num--}}})/script/body
/html
5. 本地持久化
!DOCTYPE html
html langenheadmeta charsetUTF-8 /meta http-equivX-UA-Compatible contentIEedge /meta nameviewport contentwidthdevice-width, initial-scale1.0 /link relstylesheet href./css/inputnumber.css /link relstylesheet href./css/index.css /title购物车/title/headbodydiv classapp-container idapp!-- 顶部banner --div classbanner-boximg srchttp://autumnfish.cn/static/fruit.jpg alt //div!-- 面包屑 --div classbreadcrumbspan/span/span购物车/span/div!-- 购物车主体 --div classmain v-iffruitList.length 0div classtable!-- 头部 --div classtheaddiv classtrdiv classth选中/divdiv classth th-pic图片/divdiv classth单价/divdiv classth num-th个数/divdiv classth小计/divdiv classth操作/div/div/div!-- 身体 --div classtbodydiv v-for(item, index) in fruitList :keyitem.id classtr :class{ active: item.isChecked }div classtdinput typecheckbox v-modelitem.isChecked //divdiv classtdimg :srcitem.icon alt //divdiv classtd{{ item.price }}/divdiv classtddiv classmy-input-numberbutton :disableditem.num 1 classdecrease clicksub(item.id) - /buttonspan classmy-input__inner{{ item.num }}/spanbutton classincrease clickadd(item.id) /button/div/divdiv classtd{{ item.num * item.price }}/divdiv classtdbutton clickdel(item.id)删除/button/div/div/div/div!-- 底部 --div classbottom!-- 全选 --label classcheck-allinput typecheckbox v-modelisAll/全选/labeldiv classright-box!-- 所有商品总价 --span classprice-box总价nbsp;nbsp;:nbsp;nbsp;¥nbsp;span classprice{{ totalPrice }}/span/span!-- 结算按钮 --button classpay结算( {{ totalCount }} )/button/div/div/div!-- 空车 --div classempty v-else空空如也/div/divscript srchttps://cdn.jsdelivr.net/npm/vue2/dist/vue.js/scriptscriptconst defaultArr [{id: 1,icon: http://autumnfish.cn/static/火龙果.png,isChecked: true,num: 2,price: 6,},{id: 2,icon: http://autumnfish.cn/static/荔枝.png,isChecked: false,num: 7,price: 20,},{id: 3,icon: http://autumnfish.cn/static/榴莲.png,isChecked: false,num: 3,price: 40,},{id: 4,icon: http://autumnfish.cn/static/鸭梨.png,isChecked: true,num: 10,price: 3,},{id: 5,icon: http://autumnfish.cn/static/樱桃.png,isChecked: false,num: 20,price: 34,},]const app new Vue({el: #app,data: {// 水果列表fruitList: JSON.parse(localStorage.getItem(list)) || defaultArr,},computed: {// 默认计算属性只能获取不能设置要设置需要写完整写法// isAll () {// // 必须所有的小选框都选中全选按钮才选中 → every// return this.fruitList.every(item item.isChecked)// }// 完整写法 get setisAll: {get () {return this.fruitList.every(item item.isChecked)},set (value) {// 基于拿到的布尔值要让所有的小选框 同步状态this.fruitList.forEach(item item.isChecked value)}},// 统计选中的总数 reducetotalCount () {return this.fruitList.reduce((sum, item) {if (item.isChecked) {// 选中 → 需要累加return sum item.num} else {// 没选中 → 不需要累加return sum}}, 0)},// 总计选中的总价 num * pricetotalPrice () {return this.fruitList.reduce((sum, item) {if (item.isChecked) {return sum item.num * item.price} else {return sum}}, 0)}},methods: {del (id) {this.fruitList this.fruitList.filter(item item.id ! id)},add (id) {// 1. 根据 id 找到数组中的对应项 → findconst fruit this.fruitList.find(item item.id id)// 2. 操作 num 数量fruit.num},sub (id) {// 1. 根据 id 找到数组中的对应项 → findconst fruit this.fruitList.find(item item.id id)// 2. 操作 num 数量fruit.num--}},watch: {fruitList: {deep: true,handler (newValue) {// 需要将变化后的 newValue 存入本地 转JSONlocalStorage.setItem(list, JSON.stringify(newValue))}}}})/script/body
/html 总结
欢迎各位留言交流以及批评指正如果文章对您有帮助或者觉得作者写的还不错可以点一下关注,点赞收藏支持一下。 博客的参考源码可以在我主页的资源里找到如果在学习的过程中有什么疑问欢迎大家在评论区向我提出