1、事件简写和template标签
1.1、事件简写
<button @click="nums+=100">加100</button>
data:{ // 数据
nums:2000
}
// 适用于简单的运算
1.2、template标签
-
作用: 当我们的循环或者if判断的时候,内部的内容不是一个容器标签包裹。
<template v-for="item in arr"> <div class="li">{{item}}</div> <p>对的{{item}}</p> </template> // 不会产生真的标签,只帮助我们进行渲染
2、计算属性
-
作用:不是直接展示data中的数据,而是对data中的数据进行一些处理后在进行展示。 计算属性帮助我们对data中的数据进行一些处理
-
本质:属性,和data中的变量是一样的。 也是直接挂在Vue实例上面的属性。
-
写法:
computed:{ // 计算属性 add:function(){ return 3333 }, revstr(){ return this.str.split("").reverse().join("") } }, // 渲染 {{ add }} <hr> {{revstr}}
-
注意: 值是一个函数,而且这个函数一定要有返回值,不然这个计算属性就为空
-
计算属性和方法的区别: 计算属性是依赖于缓存的,数据不变,不会更新。方法就必须每次调用。
3、监听器
-
作用:对data中的数据或者computed里面的计算属性进行监听,只要是this上面的属性都可以监听。
-
写法:
data:{ nums:200 }, watch:{ nums:function(newVal,oldVal){ // 第一个形参是新值,第二个形参是旧值 【浅监听】 console.log("nums变化了"); } } // 修改 <button @click="nums+=100">改变</button>
-
注意: 监听的数据是基本数据类型还是引用数据类型。如果是基本数据类型,那么可以像上面这么书写,如果是引用数据类型(对象和数组)就要注意,我们需要使用深监听。
data:{ // 数据 nums:200, // 基本数据类型 obj:{ // 引用数据类型 name:"张飞", age:20 } }, watch:{ // 监听器 (监听data中的数据或者计算属性的变化) nums:function(newVal,oldVal){ // 第一个形参是新值,第二个形参是旧值 console.log("nums变化了"); }, obj:{ deep:true, // 深监听 handler:function(newVal){ console.log(newVal.age); } } },
4、样式处理
4.1、操作class
-
对象语法
<h3 :class="{active:isActive,title:hasTitle,'text-box':hasBox}">222</h3> data:{ isActive:true, hasTitle:true, hasBox:true, }, // active 和 text-box 和 title 是class名称。 // isActive,hasTitle,hasBox 是data中的变量,决定要不要用,这个class // 简写: <h3 :class="classObj">222</h3> data:{ classObj:{ header:true, 'tit-nav':true, // class名带有-或者_ 那么我们需要用引号 error:false } },
-
数组语法
<h4 :class="[aaa,bbb]">3333333</h4> // aaa,bbb是变量,对应的值是class名 data:{ aaa:"box", bbb:"title" }
4.2、操作syle
-
对象语法
<h1 :style="{color:mycolor,fontSize:nums}">标题</h1> data:{ // 对象的属性名是css样式属性名,对象的属性值是 css的样式属性值 mycolor:"red", nums:"20px" } // 简写 <h1 :style="styleObj">标题</h1> data:{ styleObj:{ color:"red", fontSize:"20px" // 注意驼峰命名 } }
-
数组语法
<p :style="[aa,bb]">2222</p> data:{ aa:{ width:"20px", height:"20px", backgroundColor:"#ddd" }, bb:{ fontSize:"50px" } }
4.3、三木操作class(推荐)
-
本质:还是操作class,建议大家操作class,因为我们讲究行为结构表现三者分离
-
使用:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title></title> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <style> .box{ border: 4px solid blue; text-align: center; line-height: 40px; } .active{ background-color: red; color: #fff; } </style> </head> <body> <div id="app"> <h3 :class="state?'active box':'box'" @click="state=!state">中原一点红</h3> </div> </body> <script> new Vue({ el:"#app", data:{ state:false }, computed:{}, watch:{}, methods:{} }) // 行为(JS) 、结构(HTML) 、表现(CSS) // 三者分离 </script> </html>
5、本地存储
-
介绍:localStorage 持久存在,页面关闭了,再打开依旧存在,sessionStorage 会话存储,页面关闭了,打开就不存在。
-
方法:
// 存 localStorage.setItem(key,value); // 取 localStorage.getItem(key); // 删一个 localStorage.removeItem(key); // 删所有 localStorage.clear();
-
使用:
// 存 // setItem(key,val) // localStorage.setItem('hello',20) // 取 // getItem(key) let res = localStorage.getItem('hello'); console.log(res); // 删一个 // removeItem(key) // localStorage.removeItem('lastname'); // 删除所有 // localStorage.clear();
-
作用:
-
用户登录信息的存储
-
历史搜索记录
-
…
-
重要作用:实现页面之间的传值
-
6、跨页面之间传值
-
原因: 因为二级页面,或者三级页面,等下级页面肯定是需要从上一级页面传递一个关键字段数据过来,比如文章详情一定要接收文章的id,文章列表,一定要接收文章的分类。
-
如何实现跨页面之间的传值
- URL传参
- localStorage传值
6.1、URL传参
AA页面
<!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="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
<ul>
<li v-for="(item,index) in arr" :key="index">
<h3><a :href="'10、bb.html?id='+item.id">{{item.title}}</a></h3>
<p>{{item.description}}</p>
<img width="100px" :src="item.picimg[0].url" alt="">
</li>
</ul>
</div>
</body>
<script>
let vm = new Vue({
el:"#app",
data:{
arr:[]
},
methods:{
}
})
let ajax = new XMLHttpRequest();
ajax.open("GET","http://122.51.249.55:3030/api/article?act=getlist");
ajax.send();
ajax.onload = function(){
console.log(ajax);
let data = JSON.parse(ajax.response);
console.log(data);
vm.arr = data.data
}
// 跨页面之间传值
// url上面的search传值
// localStorage
</script>
</html>
BB 页面
<!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="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
<h3>{{article.title}}</h3>
<img :src="article.picimg[0].url" alt="">
<div v-html="article.content"></div>
</div>
</body>
<script>
// url上面获取传入的值
let id = location.search.split("=")[1]
console.log(id);
let vm =new Vue({
el:"#app",
data:{
article:""
}
})
let ajax = new XMLHttpRequest();
ajax.open("GET",`http://122.51.249.55:3030/api/article?act=find&id=${id}`);
ajax.send();
ajax.onload = function(){
console.log(ajax);
let data = JSON.parse(ajax.response);
console.log(data);
vm.article = data.data
}
</script>
</html>
6.2、 本地存储传值
AA页面
<!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="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
<ul>
<li v-for="(item,index) in arr" :key="index">
<h3 @click="go(item.id)">{{item.title}}</h3>
<p>{{item.description}}</p>
<img width="100px" :src="item.picimg[0].url" alt="">
</li>
</ul>
</div>
</body>
<script>
let vm = new Vue({
el:"#app",
data:{
arr:[]
},
methods:{
go(id){
console.log(id);
window.localStorage.setItem("articleid",id)
location.href = "10、bb.html"
}
}
})
let ajax = new XMLHttpRequest();
ajax.open("GET","http://122.51.249.55:3030/api/article?act=getlist");
ajax.send();
ajax.onload = function(){
console.log(ajax);
let data = JSON.parse(ajax.response);
console.log(data);
vm.arr = data.data
}
// 跨页面之间传值
// url上面的search传值
// localStorage
</script>
</html>
BB页面
<!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="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="app">
<h3>{{article.title}}</h3>
<img :src="article.picimg[0].url" alt="">
<div v-html="article.content"></div>
</div>
</body>
<script>
// 本次存储拿
let id = localStorage.getItem("articleid")
let vm =new Vue({
el:"#app",
data:{
article:""
}
})
let ajax = new XMLHttpRequest();
ajax.open("GET",`http://122.51.249.55:3030/api/article?act=find&id=${id}`);
ajax.send();
ajax.onload = function(){
console.log(ajax);
let data = JSON.parse(ajax.response);
console.log(data);
vm.article = data.data
}
</script>
</html>
7、填坑(修改对象和数组页面不更新)
-
问题描述:
- 当我们修改data中数组变量中的某一个值得时候(如: this.arr[1]=‘xx值’), 页面不会实现数据更新
- 当我们给data中的对象变量添加一个新的属性的时候,页面不会响应更新
- 当我们修改data中的对象变量中的某个属性的时候(属性值是引用数据类型),同样也不会响应
-
解决问题:
- 数组的问题: 使用数组常用的API方法,如push,pop,shift,unshift,splice
- 对象的问题: vue中本身存在的一个方法 this.$set(数组/对象,下标/属性名,值)
-
代码:
<!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="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> </head> <body> <div id="app"> <ul> <li v-for="(item,index) in arr" :key="index">{{index}}===={{item}}</li> </ul> <button @click="change">将第二个改成'Vue'</button> <hr> {{person}} <button @click="addsex">添加一个sex属性</button> </div> </body> <script> let vm = new Vue({ el:"#app", data:{ arr:['轮播图','ajax','tab切换','node.js'], person:{ name:"李寻欢", desc:"小李飞刀", age:20, friend:[] } }, methods:{ change(){ // this.arr[1] = 'vue' // 不响应 // this.arr[this.arr.length] = '添加的' // 不响应 // this.arr.splice(1,1,'Vue') // this.arr.push('添加的'); // console.log(this.arr); this.$set(this.arr,1,'vue') }, addsex(){ // this.person.sex = "公的" // 不响应 this.$set(this.person,'sex','公的') console.log(this.person); } } }) console.log(vm); </script> </html>
8、原生购物车功能
-
功能
// 功能需求: // 数量加减变化 // 数量加减变化 小计变化 // 数量加减变化 该行选中 // 数量加减变化 总数,总价变化 // 选中变化 总数,总价变化,全选变化 // 全选变化 选中,总价都变化 // 删除变化
-
代码:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>原生JS实现购物车功能</title> </head> <body> <table align="center" width="600" border="1"> <thead> <tr> <td>全选 <input type="checkbox" class="allcheck"></td> <td>名称</td> <td>价格</td> <td>数量</td> <td>小计</td> <td>操作</td> </tr> </thead> <tbody> </tbody> <tfoot> <tr> <td> 全选 <input type="checkbox" class="allcheck"> </td> <td colspan="5" style="text-align: right;"> 共 <span>0 </span> 件商品,共计 <span>0.00</span> 元 <button>立即结算</button> </td> </tr> </tfoot> </table> </body> <script> //数据 let data = [ { 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 } ] // 渲染数据 let htmlstr = "" for (let index = 0; index < data.length; index++) { htmlstr += ` <tr> <td><input class="check" type="checkbox"></td> <td>${data[index].title}</td> <td class="price">${data[index].price}</td> <td> <button class="jian">-</button> <input type='text' class="nums" value='${data[index].nums}' style="width:40px;text-align:center;" /> <button class="add">+</button> </td> <td class="xj">${data[index].nums*data[index].price}</td> <td> <button class="del">删除</button> </td> </tr> ` } document.querySelector("tbody").innerHTML = htmlstr // 功能需求: // 数量加减变化 // 数量加减变化 小计变化 // 数量加减变化 该行选中 // 数量加减变化 总数,总价变化 // 选中变化 总数,总价变化,全选变化 // 全选变化 选中,总价都变化 // 删除变化 // 数量加减变化 // 数量加变化 var add = document.querySelectorAll(".add"); for (var index = 0; index < add.length; index++) { add[index].onclick = function(){ var nums = this.parentNode.children[1].value; nums++; this.parentNode.children[1].value = nums; rowChange(this.parentNode.parentNode); } } // 减少变化 var jian = document.querySelectorAll(".jian"); for (var index = 0; index < jian.length; index++) { jian[index].onclick = function(){ var nums = this.parentNode.children[1].value; if(nums==1){ return; } nums--; this.parentNode.children[1].value = nums; rowChange(this.parentNode.parentNode); } } // 小计价格变化 function rowChange(dom){ var price = dom.querySelector(".price").innerHTML; var nums = dom.querySelector(".nums").value; dom.querySelector(".xj").innerHTML = price*nums; dom.querySelector(".check").checked = true; isAllCheck(); } // 单选变化 var check = document.querySelectorAll("tbody .check") for (let index = 0; index < check.length; index++) { check[index].onclick = function(){ isAllCheck(); } } // 全选变化 var allcheck = document.querySelectorAll(".allcheck"); for (let index = 0; index < allcheck.length; index++) { allcheck[index].idx = index; allcheck[index].onclick = function(){ // 获取tbody里面的单选框 var check = document.querySelectorAll("tbody .check"); for (let k = 0; k <check.length; k++) { check[k].checked = this.checked } if(this.idx==0){ allcheck[1].checked = this.checked }else{ allcheck[0].checked = this.checked } allInfo(); } } // 全选判断 function isAllCheck(){ // 判断是否所有的都被选中 let state = true; var check = document.querySelectorAll("tbody .check") for (let k = 0; k < check.length; k++) { if(!check[k].checked){ // 如果是false的时候 state = false; break; } } if(check.length==0){ state = false; } var allcheck = document.querySelectorAll(".allcheck"); allcheck[0].checked = allcheck[1].checked = state; allInfo(); // 总计 } // 总计 变化 function allInfo(){ var allnum = 0; var allprice =0; var check = document.querySelectorAll("tbody .check"); for (let k = 0; k <check.length; k++) { if(check[k].checked){ allnum++; var price = check[k].parentNode.parentNode.querySelector(".xj").innerHTML; allprice += (price*1) } } document.querySelectorAll("tfoot span")[0].innerHTML = allnum document.querySelectorAll("tfoot span")[1].innerHTML = allprice } // 删除 var del = document.querySelectorAll(".del") for (let index = 0; index < del.length; index++) { del[index].onclick = function(){ var tb = this.parentNode.parentNode.parentNode; var tr = this.parentNode.parentNode; tb.removeChild(tr); isAllCheck(); } } </script> </html> // dom查找麻烦 // 逻辑关系比较麻烦