day68:Vue:类值操作/style样式操作&v-for&filer/computed/watch&生命周期钩子函数&axios
目录
1.类值操作 :class
添加class类名,值是一个对象
<div :class="{c1:true/false}"></div>
语法:{ class类1:布尔值变量1, class类2:布尔值变量2, } 例子: <p :class="{box1:myclass1}">一个段落</p> // 布尔值变量如果是false,则不会添加对象的属性名作为样式 // 布尔值变量如果是true,则不会添加对象的属性名作为样式
类值操作常见形式
<!DOCTYPE html> <html lang="zh-CN"> <head> <title>html</title> <style> .c1{ background-color: red; font-size: 18px; } .c2{ font-size: 36px; } </style> </head> <body> <div id="app"> <!-- 根据data中的num的值来确定是否显示c1样式 --> <div :class="{c1:num==0}" class="c2">{{msg}}</div>
<!-- 根据vue传过来的data中的status的值来确定显示c1样式还是c2样式 --> <div :class="status?'c1':'c2'">{{ msg }}</div>
<!-- m1为自定义对象 --> <div :class="[m1,]">{{ msg }}</div> </div> </body> <script src="vue.js"></script> <script> let vm = new Vue({ el:'#app', data(){ return{ msg:'hello', num:0, status:true, m1:{ c1:false, c2:true, } } } }) </script> </html>
总结
// 1. 给元素绑定class类名 data:{ myObj:{ complete:true, uncomplete:false, } } // html元素: <div class="box" :class="myObj">2222</div> // 最终浏览器效果: <div class="box complete">2222</div>
2.style操作样式 :style
操作样式语法:
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <title>html</title> </head> <body> <div id="app"> <!-- style操作方式1 --> <div :style="{color:fontColor,backgroundColor:bgc}"> style操作方式1 </div> <!-- style操作方式2 --> <div :style="vuestyle"> style操作方式2 </div> </div> </body> <script src="vue.js"></script> <script> let vm = new Vue({ el: '#app', data() { return { fontColor: 'red', bgc: 'green', vuestyle: { 'color': 'red', fontSize: '80px' }, } } }) </script> </html>
3:示例:选项卡 @click+:class
实现思路:当用户点击标题栏的按钮[span]时,显示对应索引下标的内容块[.list]
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style> #card{ width: 500px; height: 350px; } .title{ height:50px; } .title span{ width: 100px; height: 50px; background-color:#ccc; display: inline-block; line-height: 50px; /* 设置行和当前元素的高度相等,就可以让文本内容上下居中 */ text-align:center; } .content .list{ width: 500px; height: 300px; background-color: yellow; display: none; } .content .active{ display: block; } .title .current{ background-color: yellow; } </style> <script src="vue.js"></script> </head> <body> <div id="card"> <div class="title"> <span @click="num=1" :class="{current:num===1}">国内新闻</span> <span @click="num=2" :class="{current:num===2}">国际新闻</span> <span @click="num=3" :class="{current:num===3}">银河新闻</span> <!--<span>{{num}}</span>--> </div> <div class="content"> <div class="list" :class="{active:num===1}">国内新闻列表</div> <div class="list" :class="{active:num===2}">国际新闻列表</div> <div class="list" :class="{active:num===3}">银河新闻列表</div> </div> </div> <script> // 思路: // 当用户点击标题栏的按钮[span]时,显示对应索引下标的内容块[.list] // 代码实现: var card = new Vue({ el:"#card", data:{ num:1, }, }); </script> </body> </html>
4.v-for示例:循环商品显示
v-for语法:
<tr v-for="(value,index) in vue中data的数据" :key="index">
<!DOCTYPE html> <html lang="zh-CN"> <head> <title>html</title> <meta charset="UTF-8"> </head> <body> <div id="app"> <table border="1"> <thead> <tr> <th>name</th> <th>price</th> </tr> </thead> <tbody> <tr v-for="(value,index) in goods" :key="index"> <td>{{ value.name }}</td> <td v-if="value.price>60" style="background-color: red">{{ value.price }}</td> <td v-else>{{ value.price }}</td> </tr> </tbody> </table> </div> </body> <script src="vue.js"></script> <script> let vm = new Vue({ el: '#app', data() { return { goods: [ {"name": "python入门", "price": 150}, {"name": "python进阶", "price": 100}, {"name": "python高级", "price": 75}, {"name": "python研究", "price": 60}, {"name": "python放弃", "price": 110}, ] } } }) </script> </html>
5.过滤器:filter
<!DOCTYPE html> <html lang="zh-CN"> <head> <title>html</title> <meta charset="UTF-8"> </head> <body> <div id="app"> <p>{{ price }}</p> <p>{{ price.toFixed(2) }}</p> <!-- 保留两位小数,四舍五入 --> <p>{{ price|yuan }}</p> <!-- 过滤器 --> <p>{{ price|global }}</p> <!-- 使用全局过滤器 --> <p>{{ price|global|yuan }}</p> <!-- 同时使用两个过滤器 --> <p>{{ price2|yuan2(2) }}</p> <!-- 过滤器传额外参数 --> </div> </body> <script src="vue.js"></script> <script> // 全局过滤器 Vue.filter('global',function (value) { return value.toFixed(3) + '圆' }); let vm = new Vue({ el:"#app", data(){ return{ price:100, price2:100.128, } }, filters:{ // vue中的过滤器 yuan(value){ return value + '元' }, yuan2(value,n){ return value.toFixed(n) + '元' } } }) </script> </html>
6.计算属性:computed
我们之前学习过字符串反转,如果直接把反转的代码写在元素中,则会使得其他同事在开发时时不易发现数据被调整了,所以vue提供了一个计算属性(computed),可以让我们把调整data数据的代码存在该属性中
<!DOCTYPE html> <html lang="zh-CN"> <head> <title>html</title> <meta charset="UTF-8"> </head> <body> <div id="app"> <p>{{ price }}</p> <p>{{ add }}</p> </div> </body> <script src="vue.js"></script> <script> var vm = new Vue({ el:'#app', data(){ return{ price1:100, price2:100.126, } }, // 计算属性 computed:{ add(){ return this.price1+ this.price2 } } }) </script> </html>
7.监听属性:watch
侦听属性,可以帮助我们侦听data某个数据的变化,从而做相应的自定义操作。
侦听属性是一个对象,它的键是要监听的对象或者变量,值一般是函数,当侦听的data数据发生变化时,会自定执行的对应函数,这个函数在被调用时,vue会传入两个形参,第一个是变化后的数据值,第二个是变化前的数据值。
<!DOCTYPE html> <html lang="zh-CN"> <head> <title>html</title> <meta charset="UTF-8"> </head> <body> <div id="app"> <p> {{ price1 }}</p> <input type="text" v-model = "price1"> <button @click="info.xx='ss'">GOGOGO</button> </div> </body> <script src="vue.js"></script> <script> let vm = new Vue({ el:"#app", data(){ return{ price1:100, price2:100.126, info:{ xx:'oo' } } }, watch:{ // 监听变量 price1(newv,oldv){ console.log(newv,oldv); if (newv == 888){ alert('恭喜你,中奖了!') } }, // 监听对象 'info.xx':function (newv,oldv) { if(newv != 'oo'){ alert('oo滚出了房间!') } } } }) </script> </html>
8.监听属性watch示例:用户名长度限制
<!DOCTYPE html> <html lang="zh-CN"> <head> <title>html</title> <meta charset="UTF-8"> </head> <body> <div id="app"> <input type="text" v-model="iptmsg"> <span style="color: red;font-size: 12px">{{msg}}</span> </div> </body> <script src="vue.js"></script> <script> let vm = new Vue({ el:'#app', data(){ return{ iptmsg:'', msg:'' } }, watch:{ // 监听input框输入的信息,判断长度是否符合要求 iptmsg(newv,oldv){ if (newv.length>4 && newv.length<10){ this.msg='' } else{ this.msg='长度不对!' } } } }) </script> </html>
9.vue对象的生命周期钩子函数
每个Vue对象在创建时都要经过一系列的初始化过程。在这个过程中Vue.js会自动运行一些叫做生命周期的的钩子函数,我们可以使用这些函数,在对象创建的不同阶段加上我们需要的代码,实现特定的功能。
<!DOCTYPE html> <html lang="zh-CN"> <head> <title>html</title> <meta charset="UTF-8"> </head> <body> <div id="app"> <p>{{ num }}</p> </div> </body> <script src="vue.js"></script> <script> let vm = new Vue({ el:'#app', data(){ return{ num:0, } }, // 触发时机:1.创建vm对象之前 2.圈地之前 3.data数据放到vm对象之前 beforeCreate(){ console.log('----beforeCreate----'); console.log(this.$el); // undefined console.log(this.$data); //undefined }, // 重要!! created(){ console.log('----created----'); console.log(this.$el); // undefined console.log(this.num); // 0 data属性的值0已经放到vm对象中 this.num = 20; }, beforeMount(){ console.log('----beforeMount----'); console.log(this.$el); // <div id="app">...</div> console.log(this.num); // 20 vm对象还没有将数据添加到我们的视图中 this.num = 30; }, // 重要!! mounted(){ console.log('----mounted----'); console.log(this.$el); // <div id="app">...</div> console.log(this.num); // 30 vm对象已经把更新后的data数据显示到页面中 } }) </script> </html>
对于生命周期钩子函数的总结
1.在vue使用的过程中,如果要初始化操作,把初始化操作的代码放在 mounted 中执行。mounted阶段就是在vm对象已经把data数据实现到页面以后。一般页面初始化使用。例如,用户访问页面加载成功以后,就要执行的ajax请求。
2.另一个就是created,这个阶段就是在 vue对象创建以后,把ajax请求后端数据的代码放进 created
vue完整的生命周期
10.阻止事件冒泡 .stop .stop.prevent
<div class="c2" @click.stop.prevent="f2"></div>
阻止时间冒泡示例
<!DOCTYPE html> <html lang="zh-CN"> <head> <title>html</title> <meta charset="UTF-8"> <style> .c1{ background-color: red; height: 200px; } .c2{ background-color: green; height: 100px; width: 100px; } </style> </head> <body> <div id="app"> <div class="c1" @click="f1"> <div class="c2" @click.stop.prevent="f2"></div> <!-- 阻止事件冒泡 --> </div> </div> </body> <script src="vue.js"></script> <script> let vm = new Vue({ el:'#app', data(){ return { price1:100, } }, methods:{ f1(){ alert('111'); }, f2(){ alert('222'); } } }) </script> </html>
11.综合示例:todolist
所用知识点:
1.v-model实时输入数据并添加到data
2.@click="add" 绑定点击时间 配合后面method中add函数
3.@click=“del(index)”绑定点击事件的函数可以携带参数,比如你要删除哪条数据
4.return返回的值:
msg 你add输入的信息,传到data,在add方法中做显示
dolist 显示的那些数据 传到前端li标签做显示
5.method写方法 add del up down
<!DOCTYPE html> <html lang="zh-CN"> <head> <title>html</title> <meta charset="UTF-8"> <style> #app{ width:600px; margin:50px auto 0; } .inputtxt{ width:550px; height:30px; border:1px solid #ccc; padding:0px; text-indent:10px; } .inputbtn{ width:40px; height:32px; padding:0px; border:1px solid #ccc; } .list{ margin:0; padding:0; list-style:none; margin-top:20px; } .list li{ height:40px; line-height:40px; border-bottom:1px solid #ccc; } .list li span{ float:left; } .list li a{ float:right; text-decoration:none; margin:0 10px; } </style> </head> <body> <div id="app"> <h2>To do list</h2> <input type="text" class="inputtxt" v-model="msg"> <input type="button" class="inputbtn" value="增加" @click="add"> <ul class="list"> <li v-for="(value,index) in dolist" :key="value.id"> <span>{{value.dosm}}</span> <a href="javascript:;" class="up" @click="up(index)">向上移一个</a> <a href="javascript:;" class="down" @click="down(index)">向下移一个</a> <a href="javascript:;" class="del" @click="del(index)">删除</a> </li> </ul> </div> </body> <script src="vue.js"></script> <script> let vm = new Vue({ el:'#app', data(){ return{ msg:'', dolist:[ {id:1,dosm:'学习html'}, {id:2,dosm:'学习css'}, {id:3,dosm:'学习javascript'}, {id:4,dosm:'学习python'}, {id:5,dosm:'学习推油'}, ] } }, methods:{ add(){ // 获取当前dolist最后一条数据 let last_ele = this.dolist[this.dolist.length-1]; if(last_ele){ let ele={ id:++last_ele.id, dosm:this.msg, }; this.dolist.push(ele); } else{ this.dolist.push( { id:1, dosm:this.sm, } ); } }, del(index){ // 从index开始删,删1个 this.dolist.splice(index,1) }, up(index){ if(index>0){ // 1.先删除要上移的那一行,并存上这行 let delEle = this.dolist.splice(index,1)[0]; // 2.找到删除的上一列,删除0行,并添加刚刚删除的那行 // index(要删除的index,删几个,替换的值) this.dolist.splice(index-1,0,delEle) } }, down(index){ let delEle = this.dolist.splice(index,1)[0]; this.dolist.splice(index+1,0,delEle); }, } }) </script> </html>
实现效果如下图所示
12.什么是钩子?
1.在A中的init方法调用一个函数
2.B继承A
3.B可以重写A预留出来的钩子方法run
4.当实例化B时,由于B中没有init,会执行其父类A中的init,而A中的init调用了run方法
如果B中重写run方法 那么执行B中的run方法
如果B中没重写run方法 那么执行A中的run方法
都是自动执行的 ,因为实例化对象时 会自动执行init方法,而init方法执行了run函数
class A: def __init__(self): self.run() def run(self): pass class B(A): def run(self): print('xxxx') b = B()
13.axios
所以使用vue的时候,一般都会使用axios的插件来实现ajax与后端服务器的数据交互。
注意,axios本质上就是javascript的ajax封装,所以会被同源策略限制。
注意,axios中的this的指向问题
axios如何使用get请求数据
// 发送get请求 // 参数1: 必填,字符串,请求的数据接口的url地址,例如请求地址:http://www.baidu.com?id=200 // 参数2:可选,json对象,要提供给数据接口的参数 // 参数3:可选,json对象,请求头信息 axios.get('服务器的资源地址',{ // http://www.baidu.com params:{ 参数名:'参数值', // id: 200, } }).then(function (response) { // 请求成功以后的回调函数 console.log("请求成功"); console.log(response); }).catch(function (error) { // 请求失败以后的回调函数 console.log("请求失败"); console.log(error.response); });
axios如何使用post提交数据
// 发送post请求,参数和使用和axios.get()一样。 // 参数1: 必填,字符串,请求的数据接口的url地址 // 参数2:必填,json对象,要提供给数据接口的参数,如果没有参数,则必须使用{} // 参数3:可选,json对象,请求头信息 axios.post('服务器的资源地址',{ username: 'xiaoming', password: '123456' },{ responseData:"json", }) .then(function (response) { // 请求成功以后的回调函数 console.log(response); }) .catch(function (error) { // 请求失败以后的回调函数 console.log(error); });
同源策略
同源策略,是浏览器为了保护用户信息安全的一种安全机制。
所谓的同源就是指代通信的两个地址(例如服务端接口地址与浏览器客户端页面地址)之间比较,是否协议、域名(IP)和端口相同。
不同源的客户端脚本[javascript]在没有明确授权的情况下,没有权限读写对方信息。
前端地址:http://www.oldboy.cn/index.html | 是否同源 | 原因 |
---|---|---|
http://www.oldboy.cn/user/login.html |
是 | 协议、域名、端口相同 |
http://www.oldboy.cn/about.html |
是 | 协议、域名、端口相同 |
https://www.oldboy.cn/user/login.html |
否 | 协议不同 ( https和http ) |
http:/www.oldboy.cn:5000/user/login.html |
否 | 端口 不同( 5000和80) |
http://bbs.oldboy.cn/user/login.html |
否 |
同源策略针对ajax的拦截代码示例
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="js/vue.js"></script> <script src="js/axios.js"></script> </head> <body> <div id="app"> <button @click="get_music">点击获取天气</button> </div> <script> let vm = new Vue({ el:"#app", data:{}, methods:{ get_music(){ axios.get("http://tingapi.ting.baidu.com/v1/restserver/ting?method=baidu.ting.search.catalogSug&query=我的中国心") .then(response=>{ console.log(response); }).catch(error=>{ console.log(error.response) }); } } }) </script> </body> </html>
运行上面代码,会出现如下错误
Access to XMLHttpRequest at 'http://tingapi.ting.baidu.com/v1/restserver/ting?method=baidu.ting.search.catalogSug&query=%E6%88%91%E7%9A%84%E4%B8%AD%E5%9B%BD%E5%BF%83'
from origin 'http://localhost:63342' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
只要出现这个关键词,就是访问受限。出现同源策略的拦截问题。
ajax跨域方案之CORS
实现CORS主要依靠<mark>后端服务器中响应数据中设置响应头信息返回</mark>的。
在django中如何设置跨域:
def post(request): response = new Response() response .set_header("Access-Control-Allow-Origin","*") return response;
或者直接在服务端的响应行中设置如下内容:
// 在响应行信息里面设置以下内容: Access-Control-Allow-Origin: ajax所在的域名地址 Access-Control-Allow-Origin: www.oldboy.cn # 表示只允许www.oldboy.cn域名的客户端的ajax跨域访问 // * 表示任意源,表示允许任意源下的客户端的ajax都可以访问当前服务端信息 Access-Control-Allow-Origin: *