Watch侦听器(监视器)
作用:监视数据变化,执行一些业务逻辑或异步操作
语法:
①简单写法 → 简单类型数据,直接监视
②完整写法 → 添加额外配置项
①简单写法
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> <div id="app"> <!-- 条件选择框 --> <div class="query"> <span>翻译成的语言:</span> <select> <option value="italy">意大利</option> <option value="english">英语</option> <option value="german">德语</option> </select> </div> <div class="box"> <div class="input-wrap"> <textarea v-model="obj.words"></textarea> <span>文档翻译</span> </div> <div class="output-wrap"> <div class="transbox">meal</div> </div> </div> </div> <script src="//i2.wp.com/cdn.jsdelivr.net/npm/[email protected]/dist/vue.js"></script> <script src="//i2.wp.com/cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script> <script> const app = new Vue({ el:'#app', data:{ //words:'' obj:{ words:'' } }, //该方法会在数据变化时调用执行 //newValue新值,oldValue老值(一般不用,可以删掉) // words(newValue,oldValue){ // } watch:{ 'obj.words' (newValue){ console.log('变化了',newValue) } } }) </script> </body> </html>
以下部分为上述代码的业务实现??(延时器:防抖)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> .output-wrap{ width: 200px; height: 200px; background-color: aquamarine; } </style> </head> <body> <div id="app"> <!-- 条件选择框 --> <div class="query"> <span>翻译成的语言:</span> <select> <option value="italy">意大利</option> <option value="english">英语</option> <option value="german">德语</option> </select> </div> <div class="box"> <div class="input-wrap"> <textarea v-model="obj.words"></textarea> <span>文档翻译</span> </div> <div class="output-wrap"> <div class="transbox">{{ result }}</div> </div> </div> </div> <script src="//i2.wp.com/cdn.jsdelivr.net/npm/[email protected]/dist/vue.js"></script> <script src="//i2.wp.com/cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script> <script> //接口地址:https://applet-base-apl-t.ithelma.net/api/translate //请求方式:get //请求参数: // 1.words:需要被翻译的文本(必传) // 2.lang:需要被翻译成的语言(可选)默认值-意大利 const app = new Vue({ el:'#app', data:{ obj:{ words:'', lang:'italy' }, result:'',//翻译结果 }, watch:{ '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>
②完整写法
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> .output-wrap{ width: 200px; height: 200px; background-color: aquamarine; } </style> </head> <body> <div id="app"> <!-- 条件选择框 --> <div class="query"> <span>翻译成的语言:</span> <select> <option value="italy">意大利</option> <option value="english">英语</option> <option value="german">德语</option> </select> </div> <div class="box"> <div class="input-wrap"> <textarea v-model="obj.words"></textarea> <span>文档翻译</span> </div> <div class="output-wrap"> <div class="transbox">{{ result }}</div> </div> </div> </div> <script src="//i2.wp.com/cdn.jsdelivr.net/npm/[email protected]/dist/vue.js"></script> <script src="//i2.wp.com/cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script> <script> //接口地址:https://applet-base-apl-t.ithelma.net/api/translate //请求方式:get //请求参数: // 1.words:需要被翻译的文本(必传) // 2.lang:需要被翻译成的语言(可选)默认值-意大利 const app = new Vue({ el:'#app', data:{ obj:{ words:'我是你爸爸', lang:'italy' }, result:'',//翻译结果 }, watch:{ //完整写法要写成一个对象 obj:{ deep:true,//深度监视:对所有都进行监视 immediate:true,//立刻执行,已进入页面,handler就立刻执行一次 handler (newValue) {//此时 handler只会在数据修改的时候触发,所以如果先设定的话,他不会自动翻译,要输入一下才能翻译 //所以就要用到第二个配置项:immediate:true clearTimeout(this.timer) this.timer = setTimeout (async () => { const res = await axios({ url:'https://applet-base-api-t.itheima.net/api/translate', params: newValue//{ //因为默认值是意大利,所以除了传words,还要传langi //words:newValue //这里的newValue包括了words和lang,所以可以直接丢newValue //} }) this.result = res.data.data console.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 // } // })i // this.result = res.data.datai // console.log(res.data.data) // },300) // }, 如果每次都要写一遍这个,太麻烦了修改此方法,可以一次性全部监视 } }) </script> </body> </html>
案例:水果购物车
</head> <body> <div class="app-container" id="app"> <!-- 顶部banner --> <div class="banner-box"><img src="//i2.wp.com/autumnfish.cn/static/fruit.jpg" alt="" /></div> <!-- 面包屑 --> <div class="breadcrumb"> <span>??</span> / <span>购物车</span> </div> <!-- 购物车主体 --> <div class="main" v-if="fruitList.length >0"> <div class="table"> <!-- 头部 --> <div class="thead"> <div class="tr"> <div class="th">选中</div> <div class="th th-pic">图片</div> <div class="th">单价</div> <div class="th num-th">个数</div> <div class="th">小计</div> <div class="th">操作</div> </div> </div> <!-- 身体 --> <div class="tbody"> <div v-for="(item,index) in fruitList" :key="item.id" class="tr" :class="{active:item.isChecked}"> <div class="td"><input type="checkbox" v-model="item.isChecked" /></div> <div class="td"><img :src="item.icon" alt="" /></div> <div class="td">{{ item.price }}</div> <div class="td"> <div class="my-input-number"> <button :disabled="item.num <=1" class="decrease" @click="sub(item.id)"> - </button> <span class="my-input__inner">{{ item.num }}</span> <button class="increase" @click="add(item.id)"> + </button> </div> </div> <div class="td">{{ item.num * item.price }}</div> <div class="td"><button @click="del(item.id)">删除</button></div> </div> </div> </div> <!-- 底部 --> <div class="bottom"> <!-- 全选 --> <label class="check-all"> <input type="checkbox" v-model="isAll" /> 全选 </label> <div class="right-box"> <!-- 所有商品总价 --> <span class="price-box">总价 : ¥ <span class="price">{{ totalPrice }}</span></span> <!-- 结算按钮 --> <button class="pay">结算( {{ totalCount }} )</button> </div> </div> </div> <!-- 空车 --> <div class="empty" v-else>??空空如也</div> </div> <script src="//i2.wp.com/cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script> <script> const defaultArr = [ { id: 1, icon: './火龙果.png', isChecked: true, num: 2, price: 6, }, { id: 2, icon: './荔枝.png', isChecked: false, num: 7, price: 20, }, { id: 3, icon: './榴莲.png', isChecked: false, num: 3, price: 40, }, { id: 4, icon: './鸭梨.png', isChecked: true, num: 10, price: 3, }, { id: 5, icon: './樱桃.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)//本身就是一个布尔值,所以=== true可以不写 // } //完整写法=get + set isAll:{ get (){ return this.fruitList.every(item => item.isChecked) }, set (value){ //基于拿到的布尔值,要让所有的小选框,同步状态 this.fruitList.forEach(item => item.isChecked = value)//一个等号赋值 } }, //统计选中的总数 totalCount(){ return this.fruitList.reduce((sum,item) => { if (item.isChecked){ //选中,需要累加 return sum + item.num } else{ //没选中,不需要累加 return sum } },0) }, //总计选中的总价 num* price,把这个再做累加 totalPrice(){ 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找到数组中的对应项 → find const fruit = this.fruitList.find(item => item.id === id)//是否和传过来的id相同, //如果是,那么就是它,然后操作数量 //2.操作num数量 fruit.num++ }, sub(id){ //1.根据id找到数组中的对应项 → find const fruit = this.fruitList.find(item => item.id === id)//是否和传过来的id相同, //如果是,那么就是它,然后操作数量 //2.操作num数量 fruit.num-- } }, watch:{ fruitList:{ deep:true, handler( newValue){ // 需要将变化后的 newValue 存入本地 (转JSON) localStorage.setItem('list',JSON.stringify(newValue)) } } } }) </script> </body> </html>