vue生命周期与侦听器
动态样式
基于vue和js语法来研究一下动态处理样式的方式
动态的class
基本模式
<div id="app">
<div :class="isShow?'show':'hidden'">
嘿嘿嘿
</div>
<p @click="isShow = !isShow">切换</p>
<p @click="change_color">变红</p>
</div>
<script>
var vue = new Vue({
el: "#app",
data: {
isShow: true,
class_arry: ['box', 'font']
},
methods: {
change_color(){
this.class_arry.unshift('red')
}
}
})
</script>
数组模式
<div id="app">
<!-- <div :class="['box', 'font', 'red']"> 基本数组结构 -->
<div :class="class_arry">
嘿嘿嘿
</div>
<p @click="change_color">变红</p>
</div>
<script>
var vue = new Vue({
el: "#app",
data: {
class_arry: ['box', 'font']
},
methods: {
change_color(){
this.class_arry.unshift('red')
}
}
})
</script>
对象模式
<div id="app">
<!-- <div :class="{'red': false,'box': true}"> -->
<div :class="class_obj">
嘿嘿嘿
</div>
<p @click="isShow = !isShow">切换</p>
<p @click="change_color">变红</p>
</div>
<script>
var vue = new Vue({
el: "#app",
data: {
isShow: true,
class_arry: ['box', 'font'],
class_obj: {'red': true,'box': true}
},
methods: {
change_color(){
this.class_arry.unshift('red')
}
}
})
</script>
动态的style
常规写法
<body>
<div id="app">
<div :style="'background-color:red'">
嘿嘿嘿
</div>
</div>
<script>
var vue = new Vue({
el: "#app",
data: {
},
})
</script>
</body>
对象写法
<body>
<div id="app">
<!-- <div :style="{'background-color':'red'}"> -->
<div :style="obj">
嘿嘿嘿
</div>
</div>
<script>
var vue = new Vue({
el: "#app",
data: {
obj:{
backgroundColor:'red'
}
},
})
</script>
</body>
数组写法
<div id="app">
<div :style="[obj,obj1]">
嘿嘿嘿
</div>
</div>
<script>
var vue = new Vue({
el: "#app",
data: {
obj:{
backgroundColor:'red'
},
obj1:{
fontSize: "24px"
}
},
})
</script>
生命周期
在vue执行的过程当中,会有几个共性关键的执行节点,我们称为生命周期节点。生命周期指的是vue实例从创建,挂载,运行到销毁的过程。
创建阶段(create)
创建阶段的生命周期函数是自动执行的
首先执行beforeCreate,然后执行created
beforeCreate 创建前
创建前,vue的变量还没有声明
created 创建后
创建后,vue的变量已经声明完成,通常用于项目的初始化
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="./vue.js"></script>
<style>
*{
margin: 0;
padding: 0;
}
</style>
</head>
<body>
<div id="app">
<div>
{{ message }}
</div>
</div>
<script>
var vue = new Vue({
el: "#app",
data: {
message: "hello world"
},
created(){
console.log(this.message,"created")
},
beforeCreate(){
console.log(this.message,"beforeCreate");
}
})
</script>
</body>
</html>
挂载阶段(mount)
beforeMount 挂载前
mounted 挂载后
挂载阶段的生命周期函数在创建阶段的生命周期函数执行完成自动执行,
beforeMount 还没有实现页面上变量数据的挂载
mounted 已经完成页面数据的挂载
<body>
<div id="app">
<div id="msg">
{{ message }}
</div>
</div>
<script>
var vue = new Vue({
el: "#app",
data: {
message: "hello world"
},
beforeMount(){
console.log(document.querySelector("#msg"),"beforeMount");
},
mounted(){
console.log(document.querySelector("#msg"),"mounted");
},
})
</script>
</body>
更新阶段(update)
beforeUpdate 更新前
updated 更新后
更新阶段的生命周期函数在挂载阶段的生命周期函数执行完成后发生数据修改自动执行,
beforeUpdate 数据修改前执行
updated 数据修改后执行
更新阶段的生命周期函数每次跟新都执行,但是挂载阶段的生命周期函数和创建阶段的生命周期函数只在第一次加载执行一次
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="./vue.js"></script>
<style>
*{
margin: 0;
padding: 0;
}
</style>
</head>
<body>
<div id="app">
<div id="msg">
{{ message }}
<input v-model="message">
</div>
</div>
<script>
var vue = new Vue({
el: "#app",
data: {
message: "hello world"
},
beforeUpdate(){
console.log(document.querySelector("#msg").innerHTML,"beforeUpdate");
},
updated(){
console.log(document.querySelector("#msg").innerHTML,"updated");
}
})
</script>
</body>
</html>
销毁阶段 (destroy)
beforeDestroy 销毁前
destroyed 销毁后
触发销毁函数后执行销毁阶段的生命周期函数,通常用来进行内存回收。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="./vue.js"></script>
<style>
*{
margin: 0;
padding: 0;
}
</style>
</head>
<body>
<div id="app">
<div id="msg">
{{ message }}
<input v-model="message">
<button @click="destroy">销毁吧</button>
</div>
</div>
<script>
var vue = new Vue({
el: "#app",
data: {
message: "hello world"
},
methods:{
destroy(){
this.$destroy()
}
},
beforeDestroy(){
console.log(this,"beforeDestroy");
},
destroyed(){
console.log(this,"destroyed");
}
})
</script>
</body>
</html>
vue的生命周期一共有四种,八个,其中两种四个自动执行,剩下的条件执行。
侦听器
方法名称: watch
作用,监听某个数据的变化,从而进行一些特殊的操作
特点:不需要调用执行,触发执行即可,类似update
注意:watch本身有一定的系统开销,所以,侦听器不可以滥用。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="./vue.js"></script>
<style>
*{
margin: 0;
padding: 0;
}
</style>
</head>
<body>
<div id="app">
<div id="msg">
{{ message }}
<input v-model="message">
</div>
</div>
<script>
var vue = new Vue({
el: "#app",
data: {
message: "hello world",
hhh: "hhh",
},
watch :{
message(new_value,old_value){
console.log(new_value,old_value)
}
}
})
</script>
</body>
</html>
深度侦听器
深度侦听器主要针对的是嵌套结构的数据修改。
<div id="app">
<div id="msg" @click="add">
{{ message }}
</div>
</div>
<script>
var vue = new Vue({
el: "#app",
data: {
message: {
msg: {
name: "王"
}
},
},
methods: {
add(){
this.message.msg.name = "李"
}
},
watch :{
message:{
handler(){
console.log(arguments);
}, //句柄
deep: true //启动深度侦听
}
}
})
</script>
计算属性
computed:作为vue当中的计算属性,主要用在页面当中的数据计算,特点:
1、调用的时候不用加括号,灵活度不够好。
2、本身具备缓存能力。
3、计算属性不可以和其他的vue变量或者功能重名。
4、计算属性的值可以读取,不可以修改
<div id="app">
<div id="msg" @click="add">
{{ add() }}
{{ add() }}
{{ add() }}
<hr />
{{ add_1 }}
{{ add_1 }}
{{ add_1 }}
<input v-model="add_2">
{{ add_1 }}
</div>
</div>
<script>
var vue = new Vue({
el: "#app",
data: {
add_2: 123
},
methods:{
add(){
console.log("add 被调用了,methods")
return 999
}
},
computed:{
add_1(){
console.log("add 被调用了,computed")
return "abc"
}
}
})
</script>
购物车案例
代码实现
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
* {
padding: 0;
margin: 0;
box-sizing: border-box;
}
.container {
width: 1000px;
margin: 20px auto;
}
.form-group {
margin: 15px 0;
}
.form-control {
height: 40px;
padding: 10px;
width: 100%;
border: 1px solid #DDD;
border-radius: 4px;
}
tr {
height: 60px;
text-align: center;
}
.active {
background-color: #EEE;
}
table {
width: 100%;
}
table,
th,
td {
border: 1px solid #CCC;
/* 合并边框 */
border-collapse: collapse;
}
label {
cursor: pointer;
}
input[type='checkbox'] {
width: 16px;
height: 16px;
vertical-align: middle;
}
.btn {
border: 0;
width: 70px;
line-height: 35px;
text-align: center;
color: #555;
background: #EEE;
border-radius: 4px;
cursor: pointer;
font-weight: 700;
outline: 0;
margin: 0 2px;
}
.btn.danger {
background-color: #D9534F;
color: #FFF;
}
.btn.success {
background-color: #337AB7;
color: #FFF;
}
.line {
border-bottom: 1px solid #DDD;
margin: 10px 0;
}
.btn-cart {
width: 30px;
height: 30px;
background: #CCC;
border: 0;
outline: none;
cursor: pointer;
}
</style>
<script src="./vue.js"></script>
</head>
<body>
<div class="container" id="app">
<h1>购物车</h1>
<table cellpadding="0" cellspacing="0" width="100%">
<thead>
<tr class="active">
<th width="80">
<label><input type="checkbox" v-model="checked" @change="toggleChecked"> 全选</label>
</th>
<th>商品</th>
<th>单价</th>
<th>数量</th>
<th>小计</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<tr v-for="(goods,index) in goods_list">
<td>
<input type="checkbox" v-model="goods.checked" @change="childCheck"/>
</td>
<td>
<img style="height: 120px;"
:src="goods.goodsimg"
alt="">
<h5>{{ goods.goodsname }}</h5>
</td>
<td>¥{{ goods.price }}</td>
<td>
<button class="btn-cart" @click="computed('d',index)">-</button>
{{ goods.num }}
<button class="btn-cart" @click="computed('u',index)">+</button>
</td>
<td>¥{{ goods.num*goods.price }}</td>
<td>
<button class="btn danger">删除</button>
</td>
</tr>
<tr>
<td colspan="6" style="text-align: left;">
<b style="color:red">
订单总金额: ¥{{ total }}
</b>
</td>
</tr>
</tbody>
</table>
</div>
</body>
<script>
var vue = new Vue({
el: "#app",
data: {
checked: false,
goods_list: [{
id: 1,
goodsname: "vivo IQ777",
goodsimg: "https://img12.360buyimg.com/seckillcms/s280x280_jfs/t1/166249/4/1781/100467/5ffc0654Eb618aa21/2188e4ef3f6abe7e.jpg.webp",
price: 2999,
num: 1,
checked: false
},
{
id: 2,
goodsname: "小米10",
goodsimg: "https://img10.360buyimg.com/seckillcms/s280x280_jfs/t1/97161/40/12127/66234/5e440190E7cd0f54e/33627b2c39a67241.jpg.webp",
price: 998,
num: 1,
checked: false
},
{
id: 3,
goodsname: "传世的珐琅锅",
goodsimg: "https://img20.360buyimg.com/seckillcms/s280x280_jfs/t1/168750/15/16697/127861/606c22c0Eca19515e/5adfe8e452fffbff.png.webp",
price: 1768,
num: 1,
checked: true
},
{
id: 4,
goodsname: "蔻驰的丑包",
goodsimg: "https://img12.360buyimg.com/ceco/s300x300_jfs/t1/119430/19/3585/133796/5eb12fe7E1a4ee264/392d83858bb8cd52.jpg!q70.jpg.webp",
price: 17865,
num: 1,
checked: false
}
]
},
methods: {
computed(type,index){
console.log(type)
if(type == "u"){
this.goods_list[index].num++
}else{
if(this.goods_list[index].num>1){
this.goods_list[index].num--
}
}
},
toggleChecked(){
//this.checked === false 全选
this.goods_list.forEach(element => {
element.checked = this.checked
});
},
childCheck(){
var ckd = true;
this.goods_list.forEach(element => {
if(!element.checked){
ckd = false
}
});
this.checked = ckd
}
},
computed: {
total(){
var price = 0;
this.goods_list.forEach(element => {
if(element.checked){
price += element.price*element.num
}
});
return price
}
}
})
</script>
</html>
删除
del(index){
this.goods_list.splice(index,1)
},
百度案例优化
jsonp
跨域问题:同源问题,在浏览器当中,为了安全,不同域名或相同域名不同端口,或者相同域名和端口,不同协议,都称为不同源的请求,不同的地址之间不可以直接发送ajax或者表单请求,但是可以发生a标签,img标签,script标签的get请求。
jsonp可以利用script标签进行数据发送,所以也先天可以免疫跨域问题,但是只能完成get请求。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="./vue.js"></script>
<style>
* {
padding: 0;
margin: 0;
box-sizing: border-box;
}
li {
list-style: none;
}
.container{
width: 600px;
margin: 20px auto;
}
.form-control {
padding: 10px;
width: 100%;
border: 1px solid #DDD;
border-radius: 4px;
vertical-align: middle;
outline: none;
}
.options{
background: #EEE;
}
.options li{
line-height: 30px;
padding: 0 10px;
cursor: pointer;
}
.options li:hover{
background: cornflowerblue;
color:#FFF;
}
</style>
</head>
<body>
<div id="app">
<div class="container">
<input class="form-control" type="text" placeholder="请输入搜索关键词" v-model="keywords"/>
<ul class="options">
<li v-for="v in search_list">{{ v }}</li>
</ul>
</div>
</div>
</body>
<script>
var vue = new Vue({
el: '#app',
data:{
keywords: "",
search_list: []
},
watch:{
keywords(value){
var url = "https://suggestion.baidu.com/su?cb=callback&wd="+value
const script = document.createElement('script')
if(this.keywords.trim() !== ""){
script.src = url
}
document.body.appendChild(script)
}
}
});
function callback(res){
vue.search_list = res.s
}
</script>
</html>