前戏
es6的基本语法
声明变量:
es5: var
es6:let const
// let块级作用域,var 函数级作用域
for(var i=0;i <=5; i++){
console.log(i)};
console.log(i);
for(let ii=0;ii <=5; ii++){
console.log(ii)};
console.log(ii);
VM517:1 Uncaught ReferenceError: ii is not defined
at <anonymous>:1:13
// let先定义在使用,var先使用在定义不会报错。
console.log(a)
var a = 100;
VM650:1 undefined
undefined
console.log(b)
let b = 200;
VM707:1 Uncaught ReferenceError: b is not defined
at <anonymous>:1:13
// let不能重新赋值定义,var可以。
var c = 100
var c = 200;
undefined
c
200
let d = 100
let d = 200;
VM856:2 Uncaught SyntaxError: Identifier 'd' has already been declared
// const定义常量
const name = 'barry';
undefined
const name = 'allen';
undefined
const name = 'allen'
const name = 'aaaa';
模板字符串:tab键上面的反引号,${变量名}来插入值 类似于python的三引号 """adfadsf""",可以写多行文本
另外还可以通过它来完成字符串格式化
示例:
let bb = 'jj';
var ss = `你好${bb}`;
console.log(ss); -- '你好jj'
es5和es6的函数对比
//ES5写法
function add(x){
return x
}
add(5);
//匿名函数
var add = function (x) {
return x
};
add(5);
//ES6的匿名函数
let add = function (x) {
return x
};
add(5);
//ES6的箭头函数,就是上面方法的简写形式
let add = (x) => {
return x
};
console.log(add(20));
//更简单的写法,但不是很易阅读
let add = x => x;
console.log(add(5));
多个参数的时候必须加括号,函数返回值还是只能有一个,没有参数的,必须写一个()
let add = (x,y) => x+y;
课上测试:
let add1 = function(a,b){
return a + b};
undefined
add1(1, 3);
4
let add2 = (a,b) => {
return a + b
};
undefined
add2(3, 4);
自定义对象(字典)中封装函数的写法
//es5对象中封装函数的方法
var name = '子俊';
var person1 = {
name:'超',
age:18,
f1:function () { //在自定义的对象中放函数的方法
console.log(this);//this指向的是当前的对象,{name: "超", age: 18, f1: ƒ}
console.log(this.name) // '超'
}
};
//<h1 id='d1'>xxx</h1>
//document.getElementById('d1').onclick = function(){this.innerText;};
person1.f1(); //通过自定对象来使用函数
//ES6中自定义对象中来封装箭头函数的写法
let name = '子俊'; -- window.name
let person2 = {
name:'超',
age:18,
//f1:function(){};
f1: () => { //在自定义的对象中放函数的方法
console.log(this); //this指向的不再是当前的对象了,而是指向了person的父级对象(称为上下文),而此时的父级对象是我们的window对象,Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, frames: Window, …}
console.log(window);//还记得window对象吗,全局浏览器对象,打印结果和上面一样:Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, frames: Window, …}
console.log(this.name) //'子俊'
}
};
person2.f1(); //通过自定对象来使用函数
person2 -- window.person2
//而我们使用this的时候,希望this是person对象,而不是window对象,所以还有下面这种写法
let person3 = {
name:'超',
age:18,
//f1:function(){};
//f1(){}
f1(){ //相当于f1:function(){},只是一种简写方式,称为对象的单体模式写法,写起来也简单,vue里面会看用到这种方法
console.log(this);//this指向的是当前的对象,{name: "超", age: 18, f1: ƒ}
console.log(this.name) //'超'
}
};
person3.f1()
一般我们在es6中的字典里面,如果定义函数,会使用单体模式,除非你是想在字典中的函数里面的this获取的是这个字典的上一级对象,使用箭头函数。
es5和es6的类写法对比(了解)
<script>
//es5写类的方式
function Person(name,age) {
//封装属性
this.name = name;
this.age = age;
}
//封装方法,原型链
Person.prototype.f1 = function () {
console.log(this.name);//this指的是Person对象, 结果:'超'
};
//封装方法,箭头函数的形式写匿名函数
Person.prototype.f2 = ()=>{
console.log(this); //Window {postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, frames: Window, …} this指向的是window对象
};
var p1 = new Person('超',18);
p1.age
p1.f1();
p1.f2();
// 相当于:
class Person:
def __init__(self,name,age):
self.name = name
self.age = age
def f1(self):
print(self.name)
p1 = Person('barry', 23)
p1.f1();
//其实在es5我们将js的基本语法的时候,没有将类的继承,但是也是可以继承的,还记得吗,那么你想,继承之后,我们是不是可以通过子类实例化的对象调用父类的方法啊,当然是可以的,知道一下就行了,我们下面来看看es6里面的类怎么写
class Person2{
constructor(name,age){ //对象里面的单体模式,记得上面将函数的时候的单体模式吗,这个方法类似于python的__init__()构造方法,写参数的时候也可以写关键字参数 constructor(name='超2',age=18)
//封装属性
this.name = name;
this.age = age;
} //注意这里不能写逗号
showname(){ //封装方法
console.log(this.name);
} //不能写逗号
showage(){
console.log(this.age);
}
}
let p2 = new Person2('超2',18);
p2.showname() //调用方法 '超2'
//es6的类也是可以继承的,这里咱们就不做细讲了,将来你需要的时候,就去学一下吧,哈哈,我记得是用的extends和super
</script>
1. vue.js的快速入门使用
1.1 vue.js库的下载
vue.js是目前前端web开发最流行的工具库,由尤雨溪在2014年2月发布的。
另外几个常见的工具库:react.js /angular.js’
vue.js其实就是高级版的jQuery。
官方网站:
中文:https://cn.vuejs.org/
英文:https://vuejs.org/
官方文档:https://cn.vuejs.org/v2/guide/
vue.js目前有1.x、2.x和3.x 版本,我们学习2.x版本的。2.x到3.x是平滑过渡的,也就是说你之前用2.x写的代码,用3.x的版本的vue.js也是没问题的。
1.2 vue.js库的基本使用
在github下载:https://github.com/vuejs/vue/releases
在官网下载地址: https://cn.vuejs.org/v2/guide/installation.html
vue的引入类似于jQuery,开发中可以使用开发版本vue.js,产品上线要换成vue.min.js。
源码:https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<script src="js/vue.min.js"></script>
</head>
<body>
<div id="app">
<!-- {{ message }} 表示把vue对象里面data属性中的对应数据输出到页面中 -->
<!-- 在双标签中显示数据要通过{{ }}来完成 -->
<p>{{ message }}</p>
</div>
</body>
<script>
// vue.js的代码开始于一个Vue对象。所以每次操作数据都要声明Vue对象开始。
var vm = new Vue({
el:'#app', // 设置当前vue对象要控制的标签范围。
// data属性写法方式1
data:{ // data是将要展示到HTML标签元素中的数据。
message: 'hello world!',
}
// 方式2
// data:function () {
// return {
// 'msg':'掀起你的盖头来1!'
// }
// }
// 方式3
data(){ // 单体模式 这种写法用的居多,并且后面学习中有个地方一定要这样写,所以我们就记下来这种写法就可以了
return {
'msg':'掀起你的盖头来2!',
}
}
});
</script>
</html>
课上测试:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Bootstrap 101 Template</title>
</head>
<body>
<div id="app">
<!-- 4. 将数据渲染到指定的圈地的标签内部 -->
{{msg}}
</div>
<script src="../vue.js"></script>
<script>
// 1. 实例化一个vue对象
let vm = new Vue({
el: '#app', // 2 圈地,语法与css/jQuery查询标签的语言一样。
// data: { // 3 构建需要渲染的数据
// 'msg': '蒲公英四期皇家会所',
//
// }
// 构建data方法二
data(){
return {
'msg': '现场美女发牌~'
}
}
})
</script>
</body>
</html>
总结:
1. vue的使用要从创建Vue对象开始
var vm = new Vue();
2. 创建vue对象的时候,需要传递参数,是自定义对象,自定义对象对象必须至少有两个属性成员
var vm = new Vue({
el:"#app",
data: {
数据变量:"变量值",
数据变量:"变量值",
数据变量:"变量值",
},
});
el:圈地,划地盘,设置vue可以操作的html内容范围,值就是css的id选择器,其他选择器也可以,但是多用id选择器。
data: 保存vue.js中要显示到html页面的数据。
3. vue.js要控制器的内容外围,必须先通过id来设置。
<div id="app">
<h1>{{message}}</h1>
<p>{{message}}</p>
</div>
vue中的变量可以直接进行一些简单直接的js操作
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>test vue</title>
</head>
<body>
<div id="app">
<!-- vue的模板语法,和django的模板语法类似 -->
<h2>{{ msg }}</h2> <!-- 放一个变量,会到data属性中去找对应的值 -->
<!-- 有人说,我们直接这样写数据不就行吗,但是你注意,我们将来的数据都是从后端动态取出来的,不能写死这些数据啊,你说对不对 -->
<h2>{{ 'hello beautiful girl!' }}</h2> <!-- 直接放一个字符串 -->
<h2>{{ num+1 }}</h2> <!-- 四则运算 -->
<h2>{{ 2+1 }}</h2> <!-- 四则运算 -->
<h2>{{ {'name':'chao'} }}</h2> <!-- 直接放一个自定义对象 -->
<h2>{{ person.name }}</h2> <!-- 下面data属性里面的person属性中的name属性的值 -->
<h2>{{ 1>2?'真的':'假的' }}</h2> <!-- js的三元运算 -->
<h2>{{ msg2.split('').reverse().join('') }}</h2> <!-- 字符串反转 -->
</div>
<!-- 1.引包 -->
<script src="vue.js"></script>
<script>
//2.实例化对象
new Vue({
el:'#app',
data:{
msg:'黄瓜',
person:{
name:'超',
},
msg2:'hello Vue',
num:10,
}
})
</script>
</body>
</html>
1.3 vue.js的M-V-VM思想
MVVM 是Model-View-ViewModel 的缩写,它是一种基于前端开发的架构模式。
Model
指代的就是vue对象的data属性里面的数据。这里的数据要显示到页面中。
View
指代的就是vue中数据要显示的HTML页面,在vue中,也称之为“视图模板” 。
ViewModel
指代的是vue.js中我们编写代码时的vm对象了,它是vue.js的核心,负责连接 View 和 Model,保证视图和数据的一致性,所以前面代码中,data里面的数据被显示中p标签中就是vm对象自动完成的。
这个渲染是实时渲染,只要Model中的数据发生变化,vm对象马上将此数据自动的渲染到view视图模板中。
编写代码,让我们更加清晰的了解MVVM:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="js/vue.min.js"></script>
<script>
window.onload = function(){
// 创建vm对象
var vm = new Vue({
el: "#app",
data: {
name:"大标题",
age:16,
},
})
}
</script>
</head>
<body>
<div id="app">
<!-- 在双标签中显示数据要通过{{ }}来完成 -->
<h1>{{name}}</h1>
<p>{{age}}</p>
<!-- 在表单输入框中显示数据要使用v-model来完成,模板语法的时候,我们会详细学习 -->
<input type="text" v-model="name">
</div>
</body>
</html>
在浏览器中可以在 console.log通过 vm对象可以直接访问el和data属性,甚至可以访问data里面的数据
console.log(vm.$el) # #box vm对象可以控制的范围
console.log(vm.$data); # vm对象要显示到页面中的数据
console.log(vm.message);# 这个 message就是data里面声明的数据,也可以使用 vm.变量名显示其他数据,message只是举例.
总结:
1. 如果要输出data里面的数据作为普通标签的内容,需要使用{{ }}
用法:
vue对象的data属性:
data:{
name:"小明",
}
标签元素:
<h1>{{ name }}</h1>
2. 如果要输出data里面的数据作为表单元素的值,需要使用vue.js提供的元素属性v-model
用法:
vue对象的data属性:
data:{
name:"小明",
}
表单元素:
<input v-model="name">
使用v-model把data里面的数据显示到表单元素以后,一旦用户修改表单元素的值,则data里面对应数据的值也会随之发生改变,甚至,页面中凡是使用了这个数据都会发生变化。
2. Vue指令系统的常用指令
指令 (Directives) 是带有“v-”前缀的特殊属性。每一个指令在vue中都有固定的作用。
在vue中,提供了很多指令,常用的有:v-html、v-if、v-model、v-for等等。
2.1 文本指令v-html和v-text(操作标签里面的数据)
v-text相当于js代码的innerText,相当于我们上面说的模板语法,直接在html中插值了,插的就是文本,如果data里面写了个标签,那么通过模板语法渲染的是文本内容,这个大家不陌生,这个v-text就是辅助我们使用模板语法的
v-html相当于innerHtml
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>test vue</title>
</head>
<body>
<div id="app">
<!-- vue的模板语法 -->
<div>{{ msg }}</div>
<div v-text="msg"></div>
<div v-html="msg"></div>
</div>
<script src="vue.js"></script>
<script>
new Vue({
el:'#app',
data(){
//记着data中是一个函数,函数中return一个对象,可以是一个空对象,但必须return
return{
msg:'<h2>超</h2>', //后端返回的是标签,那么我们就可以直接通过v-html渲染出来标签效果
}
}
})
</script>
</body>
</html>
指令会在vm对象的data属性的数据发生变化时,会同时改变元素中的其控制的内容或属性。
因为vue的历史版本原因,所以有一部分指令都有两种写法:
vue1.x写法 vue2.x的写法
v-html ----> {{ }} # vue2.x 也支持v-html
v-bind:属性名 ----> :属性
v-on:事件名 ----> @事件名
2.2 条件渲染指令v-if和v-show
vue中提供了两个指令可以用于判断是否要显示元素,分别是v-if和v-show。
2.4.1 v-if
标签元素:
<!-- vue对象最终会把条件的结果变成布尔值 -->
<h1 v-if="ok">Yes</h1>
data数据:
data:{
ok:false // true则是显示,false是隐藏
}
2.2.2 v-else
v-else指令来表示 v-if 的“else 块”,v-else 元素必须紧跟在带 v-if 或者 v-else-if 的元素的后面,否则它将不会被识别。
标签元素:
<h1 v-if="ok">Yes</h1>
<h1 v-else>No</h1>
data数据:
data:{
ok:false // true则是显示,false是隐藏
}
2.2.3 v-else-if
在vue2.1.0版本之后,又添加了v-else-if,v-else-if
,顾名思义,充当 v-if
的“else-if 块”,可以连续使用。
可以出现多个v-else-if语句,但是v-else-if之前必须有一个v-if开头。后面可以跟着v-else,也可以没有。
标签元素:
<h1 v-if="num===1">num的值为1</h1>
<h1 v-else-if="num===2">num的值为2</h1>
<h1 v-else>num的值是{{num}}</h1>
data数据:
data:{
num:2
}
2.2.4 v-show
标签元素:
<h1 v-show="ok">Hello!</h1>
data数据:
data:{
ok:false // true则是显示,false是隐藏
}
课堂测试:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Bootstrap 101 Template</title>
</head>
<body>
<div id="app">
<div v-show="status">{{msg}}</div>
<div v-if="!status">{{msg}}</div>
<div v-if="!status">蒲公英四期111</div>
<div v-if="age>=19">随便整!</div>
<div v-else-if="age==18">自己动手,丰衣足食</div>
<div v-else>太小了,再等等</div>
</div>
<script src="../vue.js"></script>
<script>
// 1. 实例化一个vue对象
let vm = new Vue({
el: '#app', // 2 圈地,语法与css/jQuery查询标签的语言一样。
data() {
return {
"msg": '蒲公英四期',
'status': false,
'age': 18,
}
}
})
</script>
</body>
</html>
简单总结v-if和v-show
v-show后面不能v-else或者v-else-if
v-show隐藏元素时,使用的是display:none来隐藏的,而v-if是直接从HTML文档中移除元素[DOM操作中的remove]
v-if 是“真正”的条件渲染,因为它会确保在切换过程中条件块内的事件监听器和子组件适当地被销毁和重建。
v-if 也是惰性的:如果在初始渲染时条件为假,则什么也不做——直到条件第一次变为真时,才会开始渲染条件块。
相比之下,v-show 就简单得多——不管初始条件是什么,元素总是会被渲染,并且只是简单地基于 CSS 进行切换。
一般来说,v-if 有更高的切换开销,而 v-show 有更高的初始渲染开销。因此,如果需要非常频繁地切换,则使用 v-show 较好;如果在运行时条件很少改变,则使用 v-if 较好。
2.3 操作属性v-bind
格式:
<标签名 :标签属性="data属性"></标签名>
<p :title="str1">{{ str1 }}</p> <!-- 也可以使用v-html显示双标签的内容,{{ }} 是简写 -->
<a :href="url2">淘宝</a>
<a v-bind:href="url1">百度</a> <!-- v-bind是vue1.x版本的写法 -->
课堂测试:
<div id="app">
<a href="{{url}}">百度一下</a> // 这种方式不可以
<a :href="url">百度一下</a>
</div>
<script src="../vue.js"></script>
<script>
// 1. 实例化一个vue对象
let vm = new Vue({
el: '#app', // 2 圈地,语法与css/jQuery查询标签的语言一样。
data() {
return {
'url': 'http://www.baidu.com',
}
}
})
</script>
</body>
</html>
绑定事件 @进行绑定。
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Bootstrap 101 Template</title>
</head>
<body>
<div id="app">
<div>{{msg}}</div>
<button @click="cli">点击</button>
</div>
<script src="../vue.js"></script>
<script>
// 1. 实例化一个vue对象
let vm = new Vue({
el: '#app', // 2 圈地,语法与css/jQuery查询标签的语言一样。
data() {
return {
'msg': '蒲公英四期皇家会所',
}
},
methods: {
cli(){
this.msg = '美女现场发牌~';
}
}
})
</script>
</body>
</html>
显示wifi密码效果:配合v-on事件绑定
方法一:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Bootstrap 101 Template</title>
</head>
<body>
<div id="app">
<input :type="type">
<button @click="cli">切换显示状态</button>
</div>
<script src="../vue.js"></script>
<script>
// 1. 实例化一个vue对象
let vm = new Vue({
el: '#app', // 2 圈地,语法与css/jQuery查询标签的语言一样。
data() {
return {
'type': 'text',
}
},
methods: {
cli(){
if(this.type==='text'){
this.type = 'password';
}else{
this.type= 'text';
}
}
}
})
</script>
</body>
</html>
方法二:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Bootstrap 101 Template</title>
</head>
<body>
<div id="app">
<input :type="type">
<button @click="type=(type==='text'?'password':'text')">切换显示状态</button>
</div>
<script src="../vue.js"></script>
<script>
// 1. 实例化一个vue对象
let vm = new Vue({
el: '#app', // 2 圈地,语法与css/jQuery查询标签的语言一样。
data() {
return {
'type': 'text',
}
},
})
</script>
</body>
</html>S
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="js/vue.js"></script>
</head>
<body>
<div id="index">
<img :src="url" :alt="title"><br>
<input :type="type" placeholder="请输入wifi密码"> <button @click="type='text'">显示密码</button>
<!--切换密码显示写法,但是一般不建议将这么复杂的逻辑直接写到属性值里面,一般通过事件操作来玩,下面就说一下事件操作-->
<button @click="type=(type=='password'?'text':'password')">切换显示密码</button>
// 还可以按照下面的方式用,但必须是{}包裹
<p v-bind:class="{active:status===false}">你是个p</p>
<p v-bind:class="{active:status}">你是个p</p>
</div>
<script>
let vm = new Vue({
el:"#index",
data:{
url:"https://www.luffycity.com/static/img/head-logo.a7cedf3.svg",
title:"路飞学成",
type:"password",
status:false,
}
})
</script>
</body>
</html>
2.4 事件绑定v-on和methods属性
有两种事件操作的写法,@事件名 和 v-on:事件名
<button v-on:click="num++">按钮</button> <!-- v-on 是vue1.x版本的写法 -->
<button @click="num+=5">按钮2</button>
总结:
1. 使用@事件名来进行事件的绑定
语法:
<h1 @click="num++">{{num}}</h1>
2. 绑定的事件的事件名,全部都是js的事件名:
@submit ---> onsubmit
@focus ---> onfocus
....
例1:wifi密码切换显示
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="js/vue.js"></script>
</head>
<body>
<div id="index">
<img :src="url" :alt="title"><br>
<input :type="type" placeholder="请输入wifi密码">
<button @click="clickhander">{{type_tips}}</button>
<button @mouseover="clickhander">{{type_tips}}</button> <!--事件名称都是按照js中的事件名称来的,所以可以使用的事件很多-->
<button v-on:click="clickhander">{{type_tips}}</button>
</div>
<script>
let vm = new Vue({
el:"#index",
// 在data可以定义当前vue对象调用的属性,调用格式: this.变量名,例如: this.title
data:{
url:"https://www.luffycity.com/static/img/head-logo.a7cedf3.svg",
title:"路飞学成",
type:"password",
type_tips: "显示密码",
},
methods:{ // 在methods中可以定义当前vue对象调用的方法,调用格式:this.方法名(),例如: this.clickhander()
clickhander(){
// alert(this.type); // 调用上面的data里面的数据
if(this.type=="password"){
this.type="text";
this.type_tips="隐藏密码";
}else{
this.type="password";
this.type_tips="显示密码";
}
}
}
})
</script>
</body>
</html>
例2:完成商城的商品增加减少数量
课上代码:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Bootstrap 101 Template</title>
</head>
<body>
<div id="app">
<button @click="reduce">减少</button>
<input type="text" :value="num">
<button @click="num++">增加</button>
</div>
<script src="../vue.js"></script>
<script>
// 1. 实例化一个vue对象
let vm = new Vue({
el: '#app', // 2 圈地,语法与css/jQuery查询标签的语言一样。
data() {
return {
'num': 1,
}
},
methods: {
reduce: function () {
if (this.num >= 1){
this.num = this.num -1
}
}
}
})
</script>
</body>
</html>
步骤:
- 给vue对象添加操作数据的方法
- 在标签中使用指令调用操作数据的方法
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="js/vue.js"></script>
</head>
<body>
<div id="box">
<button @click="++num">+</button>
<input type="text" v-model="num">
<button @click="sub">-</button> <!-- 有人说--也可以,是的,但是单纯的使用--你会发现,数据会出现负数,负数是不合理的,所以要加判断,逻辑就复杂一些了,直接写在属性值里面不太好,那么想到的就是事件 -->
</div>
<script>
let vm = new Vue({
el:"#box",
data:{
num:0,
},
methods:{
// sub:function(){},下面是这个写法的缩写
sub(){
if(this.num<=1){
this.num=0;
}else{
this.num--;
}
}
}
})
</script>
</body>
</html>
<!--#box>(button+input+button) tab键,快速生成html标签-->
2.5 操作样式
2.5.1 控制标签class类名
格式:
<h1 :class="值">元素</h1> 值可以是对象、对象名、数组(数组的方式用的比较少)
课上操作:
-
方法一
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>Bootstrap 101 Template</title> <style> .c1 { font-size: 40px; } .c2 { color: red; } </style> </head> <body> <div id="app"> <div :class="{c1:status1,c2:status2}">三四月份第二波疫情。。。。</div> <div :class="{c1:status1,c2:!status2}">三四月份第二波疫情。。。。</div> </div> <script src="../vue.js"></script> <script> // 1. 实例化一个vue对象 let vm = new Vue({ el: '#app', // 2 圈地,语法与css/jQuery查询标签的语言一样。 data() { return { "status1": true, "status2": false, } }, }) </script> </body> </html>
-
方式二
<style> .c1 { font-size: 40px; } .c2 { color: red; } </style> </head> <body> <div id="app"> <div :class="cc">三四月份第二波疫情。。。。</div> </div> <script src="../vue.js"></script> <script> // 1. 实例化一个vue对象 let vm = new Vue({ el: '#app', // 2 圈地,语法与css/jQuery查询标签的语言一样。 data() { return { "cc": { 'c1': true, 'c2': true, } } }, }) </script>
-
方式三
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>Bootstrap 101 Template</title> <style> .c1 { font-size: 40px; } .c2 { color: red; } .c3 { background-color: yellow; } </style> </head> <body> <div id="app"> <div :class="[mycls1, mycls2]">三四月份第二波疫情。。。。</div> </div> <script src="../vue.js"></script> <script> // 1. 实例化一个vue对象 let vm = new Vue({ el: '#app', // 2 圈地,语法与css/jQuery查询标签的语言一样。 data() { return { "mycls1": { 'c1': true, 'c2': true, }, "mycls2": { 'c3': true, } } }, }) </script> </body> </html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="js/vue.js"></script>
<style>
.box1{
color: red;
border: 1px solid #000;
}
.box2{
background-color: orange;
font-size: 32px;
}
</style>
</head>
<body>
<div id="box">
<!--- 添加class类名,值是一个对象
{
class类1:布尔值变量1,
class类2:布尔值变量2,
}
-->
<p :class="{box1:myclass1}">一个段落</p>
<p @click="myclass3=!myclass3" :class="{box1:myclass2,box2:myclass3}">一个段落</p>
</div>
<script>
let vm1=new Vue({
el:"#box",
data:{
myclass1:false, // 布尔值变量如果是false,则不会添加对象的属性名作为样式
myclass2:true, // 布尔值变量如果是true,则不会添加对象的属性名作为样式
myclass3:false,
},
})
</script>
<!-- 上面的代码可以:class的值保存到data里面的一个变量,然后使用该变量作为:class的值 -->
<style>
.box4{
background-color: red;
}
.box5{
color: green;
}
</style>
<div id="app">
<button @click="mycls.box4=!mycls.box4">改变背景</button>
<button @click="mycls.box5=!mycls.box5">改变字体颜色</button>
<p :class="mycls">第二个段落</p>
<!-- 还有下面这种将类值当作属性值来操作的方式 -->
<p :class="status?'bg1':'bg2'">一段文本</p> <!-- 注意,bg1必须加引号 -->
</div>
<script>
let vm2 = new Vue({
el:"#app",
data:{
mycls:{
box4:false,
box5:true
},
status:true,
}
})
</script>
<!-- 批量给元素增加多个class样式类 -->
<style>
.box6{
background-color: red;
}
.box7{
color: green;
}
.box8{
border: 1px solid yellow;
}
</style>
<div id="app2">
<p :class="[mycls1,mycls2]">第三个段落</p>
</div>
<script>
let vm3 = new Vue({
el:"#app2",
data:{
mycls1:{
box6:true,
box7:true,
},
mycls2:{
box8:true,
}
}
})
</script>
</body>
</html>
总结:
1. 给元素绑定class类名,最常用的就是第二种。
vue对象的data数据:
data:{
myObj:{
complete:true,
uncomplete:false,
}
}
html元素:
<div class="box" :class="myObj">2222</div>
最终浏览器效果:
<div class="box complete">2222</div>
2.5.2 控制标签style样式
课上测试:
// 方式一 常用
<span :style="s1">{{msg}}</span>
data: {
msg: '蒲公英IT教育',
s1: {
color: 'red',
fontSize: '30px',
}
},
// 方式二
<span :style="{backgroundColor:bc, fontSize: fs}">{{msg}}</span>
data: {
msg: '蒲公英IT教育',
bc: 'blue',
fs: '40px',
},
// 方式三
<span :style="[style1, style2]">{{msg}}</span>
data: {
msg: '蒲公英IT教育',
style1: {
backgroundColor: 'red',
},
style2: {
fontSize: '40px',
color: 'blue',
}
},
格式1:值是json对象,对象写在元素的:style属性中
标签元素:
<div :style="{color: activeColor, fontSize: fontSize + 'px' }"></div>
<!-- 注意:不能出现中横杠,有的话就套上'font-size',或者去掉横杠,后一个单词的首字母大写,比如fontSize -->
data数据如下:
data: {
activeColor: 'red',
fontSize: 30
}
格式2:值是对象变量名,对象在data中进行声明
标签元素:
<div v-bind:style="styleObject"></div>
data数据如下:
data: {
styleObject: {
color: 'red',
fontSize: '13px'
}
}
格式3:值是数组
标签元素:
<div v-bind:style="[style1, style2]"></div>
data数据如下:
data: {
style1:{
color:"red"
},
style2:{
background:"yellow",
fontSize: "21px"
}
}
2.5.2 实例-vue版本选项卡
课上代码:
<!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>
</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>
var card = new Vue({
el: "#card",
data: {
num: 1,
},
});
</script>
</body>
</html>
<!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="js/vue.js"></script>
</head>
<body>
<div id="card">
<div class="title">
<span @click="num=0" :class="num==0?'current':''">国内新闻</span>
<span @click="num=1" :class="num==1?'current':''">国际新闻</span>
<span @click="num=2" :class="num==2?'current':''">银河新闻</span>
<!--<span>{{num}}</span>-->
</div>
<div class="content">
<div class="list" :class="num==0?'active':''">国内新闻列表</div>
<div class="list" :class="num==1?'active':''">国际新闻列表</div>
<div class="list" :class="num==2?'active':''">银河新闻列表</div>
</div>
</div>
<script>
// 思路:
// 当用户点击标题栏的按钮[span]时,显示对应索引下标的内容块[.list]
// 代码实现:
var card = new Vue({
el:"#card",
data:{
num:0,
},
});
</script>
</body>
</html>
2.6 列表渲染指令v-for
课上测试:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Bootstrap 101 Template</title>
</head>
<body>
<div id="app">
<ul>
<li v-for="(value,index) in book_list" :key="value.id">
{{value.id}} ---> {{value.title}} --->{{value.price}}
</li>
</ul>
</div>
<script src="../vue.js"></script>
<script>
let vm = new Vue({
el: '#app',
data() {
return {
book_list: [
{"id": 1, "title": "图书名称1", "price": 210},
{"id": 2, "title": "图书名称2", "price": 130},
{"id": 3, "title": "图书名称3", "price": 500},
{"id": 4, "title": "图书名称4", "price": 10},
]
}
},
})
</script>
</body>
</html>
在vue中,可以通过v-for指令可以将一组数据渲染到页面中,数据可以是数组或者对象。
数据是数组:
<ul>
<!--i是列表的每一个元素-->
<li v-for="book in book_list">{{book.title}}</li>
</ul>
<ul>
<!-- v-for不仅可以遍历数组,还可以遍历对象,这里大家记住v-for里面的一个东西 :key, 就是v-bind:key,这个key是干什么的呢,就是为了给现在已经渲染好的li标签做个标记,以后即便是有数据更新了,也可以在这个li标签里面进行数据的更新,不需要再让Vue做重新生成li标签的dom操作,提高页面渲染的性能,因为我们知道频繁的添加删除dom操作对性能是有影响的,我现在将数据中的id绑定到这里,如果数据里面有id,一般都用id,如果没有id,就绑定v-for里面那个index(当然你看你给这个索引取的变量名是什么,我这里给索引取的名字是index),这里面它用的是diff算法,回头再说这个算法 -->
<!-- <li v-for="(item,index) in data.users" :key="item.id" @click> 还可以绑定事件 -->
<li v-for="(item,index) in book_list" :key="item.id"> 第{{index+1}}本图书:{{book.title}}</li>
<!-- v-for的优先级最高,先把v-for遍历完,然后给:key加数据,还有,如果没有bind这个key,有可能你的页面都后期用动态数据渲染的时候,会出现问题,所以以后大家记着,一定写上v-bind:key -->
</ul>
<script>
var vm1 = new Vue({
el:"#app",
data:{
book_list:[
{"id":1,"title":"图书名称1","price":200},
{"id":2,"title":"图书名称2","price":200},
{"id":3,"title":"图书名称3","price":200},
{"id":4,"title":"图书名称4","price":200},
]
}
})
</script>
数据是对象:
<ul>
<!--i是每一个value值-->
<li v-for="value in book">{{value}}</li>
</ul>
<ul>
<!--value是每一个value值,attr是每一个键名-->
<li v-for="value,attr in book">{{attr}}:{{value}}</li>
</ul>
<script>
var vm1 = new Vue({
el:"#app",
data:{
book: {
// "attr属性名":"value属性值"
"id":11,
"title":"图书名称1",
"price":200
},
},
})
</script>
练习:
goods:[
{"name":"python入门","price":150},
{"name":"python进阶","price":100},
{"name":"python高级","price":75},
{"name":"python研究","price":60},
{"name":"python放弃","price":110},
]
# 把上面的数据采用table表格输出到页面,价格大于60的那一条数据需要添加背景色
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Bootstrap 101 Template</title>
<style>
.c1 {
background-color: red;
}
</style>
</head>
<body>
<div id="app">
<table border="1">
<thead>
<tr>
<th>序号</th>
<th>书籍名称</th>
<th>价格</th>
</tr>
</thead>
<tbody>
<tr v-for="(value,index) in goods" :key="index">
<td>{{index+1}}</td>
<td>{{value.name}}</td>
<td :class="{c1:value.price>60}">{{value.price}}</td>
</tr>
</tbody>
</table>
</div>
<script src="../vue.js"></script>
<script>
let vm = new Vue({
el: '#app',
data() {
return {
goods: [
{"name": "python入门", "price": 15},
{"name": "python进阶", "price": 10},
{"name": "python高级", "price": 75},
{"name": "python研究", "price": 50},
{"name": "python放弃", "price": 110},
]
}
},
})
</script>
</body>
</html>
3. Vue对象提供的属性功能
3.1 过滤器
过滤器,就是vue允许开发者自定义的文本格式化函数,可以使用在两个地方:输出内容和操作数据中。
定义过滤器的方式有两种,全局和局部过滤器
过滤器就是对渲染到页面上的数据进行再一次加工,与Django的模版渲染系统的过滤器相似。
3.1.1 使用Vue.filter()进行全局定义
Vue.filter("RMB1", function(v){
//就是来格式化(处理)v这个数据的
if(v==0){
return v
}
return v+"元"
})
3.1.2 在vue对象中通过filters属性来定义
var vm = new Vue({
el:"#app",
data:{},
filters:{
RMB2:function(value){
if(value==''){
return;
}else{
return '¥ '+value;
}
}
}
});
示例:数据小数点保留3位,并在后面加上一个元字
Filter.js
// 全局过滤器
// Vue.filter("过滤器名称","调用过滤器时执行的函数")
Vue.filter("RMB",function(value){
return value+"元";
});
html文件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="js/vue.js"></script>
<script src="js/filters.js"></script>
</head>
<body>
<div id="app">
价格:{{price.toFixed(3)}}<br>
价格:{{price|keepdot2(3)|RMB}}<br>
价格:{{price|keepdot2(3)|RMB}}<br>
价格:{{price|keepdot2(3)|RMB}}<br>
价格:{{price|keepdot2(3)}}<br>
</div>
<script>
var vm1 = new Vue({
el:"#app",
data:{
price: 20.3
},
methods:{},
// 普通过滤器[局部过滤器]
filters:{
keepdot2(value,dot){ //这里有两个参数,第二个参数必须是调用过滤器时过滤器函数名称括号里面的值
return value.toFixed(dot)
}
}
})
</script>
</body>
</html>
课上测试:
局部过滤器:
<div id="app">
<div>{{money|RMB}}</div>
</div>
<script src="../vue.js"></script>
<script>
let vm = new Vue({
el: '#app',
data() {
return {
money: 198.56,
}
},
filters: {
RMB: function (val) {
return val + '元';
}
}
})
全局过滤器:
<div id="app">
<div>{{money|RMB}}</div>
<div>{{msg|sli}}</div>
</div>
<script src="../vue.js"></script>
<script>
Vue.filter('sli', function (val) {
return val.slice(1, 4)
})
3.2 计算和侦听属性
3.2.1 计算属性
我们之前学习过字符串反转,如果直接把反转的代码写在元素中,则会使得其他同事在开发时时不易发现数据被调整了,所以vue提供了一个计算属性(computed),可以让我们把调整data数据的代码存在在该属性中。其实计算属性主要用于监听,可以监听多个对象,后面学了监听之后再说。
计算属性:对渲染的数据进行进一步加工,与过滤器相似,唯一的区别:过滤器是先将数据渲染然后在加工,计算属性是先加工数据形成最终的数据之后,在渲染页面。
课上测试:
let n = 46.789;
undefined
n.toFixed(2); 保留小数位数
'46.79'
计算属性:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Bootstrap 101 Template</title>
<style>
.c1 {
background-color: red;
}
</style>
</head>
<body>
<div id="app">
<div>{{money|RMB}}</div>
<div>{{msg|sli}}</div>
<div>{{str_rev}}</div>
</div>
<script src="../vue.js"></script>
<script>
Vue.filter('sli', function (val) {
return val.slice(1, 4)
})
let vm = new Vue({
el: '#app',
data() {
return {
money: 198.56,
msg: '蒲公英四期全体成员',
}
},
computed: {
str_rev: function () {
return this.msg.split('').reverse().join('')
}
}
})
</script>
</body>
</html>
计算属性vs过滤器:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Bootstrap 101 Template</title>
<style>
.c1 {
background-color: red;
}
</style>
</head>
<body>
<div id="app">
{{money|RMB(2)}}
{{newPrice}}
</div>
<script src="../vue.js"></script>
<script>
let vm = new Vue({
el: '#app',
data() {
return {
money: 198.567,
}
},
filters: {
RMB: function (v1,v2) {
return v1.toFixed(v2) + '元';
}
},
computed: {
newPrice: function () {
return this.money.toFixed(2) + '元';
}
}
})
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="js/vue.min.js"></script>
<script>
window.onload = function(){
var vm = new Vue({
el:"#app",
data:{
str1: "abcdefgh"
},
computed:{ //计算属性:里面的函数都必须有返回值
strRevs: function(){
var ret = this.str1.split("").reverse().join("");
return ret
}
}
});
}
</script>
</head>
<body>
<div id="app">
<p>{{ str1 }}</p>
<p>{{ strRevs }}</p>
</div>
</body>
</html>
示例:过滤器和计算属性的简单对比
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="js/vue.js"></script>
<script src="js/filters.js"></script>
</head>
<body>
<div id="app">
原价格:{{price|k2}}<br>
折扣价:{{new_price}}<br>
</div>
<script>
var vm1 = new Vue({
el:"#app",
data:{
price: 20.3,
sale: 0.6,
},
// 过滤器
filters:{
k2(value){
return value.toFixed(2)
}
},
// 计算属性
computed:{
new_price(){
return (this.price*this.sale).toFixed(2);
}
}
})
</script>
</body>
</html>
3.2.2 监听属性
侦听属性,可以帮助我们侦听data某个数据的变化,从而做相应的自定义操作。
侦听属性是一个对象,它的键是要监听的对象或者变量,值一般是函数,当侦听的data数据发生变化时,会自定执行的对应函数,这个函数在被调用时,vue会传入两个形参,第一个是变化后的数据值,第二个是变化前的数据值。
课上测试:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Bootstrap 101 Template</title>
</head>
<body>
<div id="app">
<div>{{msg}}</div>
<button @click="cli">走你</button>
</div>
<script src="../vue.js"></script>
<script>
let vm = new Vue({
el: '#app',
data() {
return {
msg: '伽罗',
}
},
methods: {
cli(){
this.msg = this.msg + '大后期';
}
},
watch: {
'msg': function (newstr, oldstr) {
console.log(newstr, oldstr)
}
}
})
</script>
</body>
</html>
v-model双向数据绑定
一般用于input标签,他可以反向作用于数据属性。
课上测试:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Bootstrap 101 Template</title>
</head>
<body>
<div id="app">
<!-- <div>{{msg}}</div>-->
<!-- <button @click="cli">走你</button>-->
<input type="text" v-model="msg">
</div>
<script src="../vue.js"></script>
<script>
let vm = new Vue({
el: '#app',
data() {
return {
msg: '伽罗',
}
},
methods: {
},
watch: {
'msg': function (newstr, oldstr) {
console.log(this.msg)
}
}
})
</script>
</body>
</html>
练习测试:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Bootstrap 101 Template</title>
</head>
<body>
<div id="app">
<!-- <div>{{msg}}</div>-->
<!-- <button @click="cli">走你</button>-->
<input type="text" v-model="msg">
</div>
<script src="../vue.js"></script>
<script>
let vm = new Vue({
el: '#app',
data() {
return {
msg: '用户名不超过8位',
}
},
methods: {
},
watch: {
'msg': function (newstr, oldstr) {
if (newstr.length >= 8){
alert('太长了!')
}
}
}
})
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="js/vue.js"></script>
<script>
window.onload = function(){
var vm = new Vue({
el:"#app",
data:{
num:20
},
watch:{
num:function(newval,oldval){
//num发生变化的时候,要执行的代码
console.log("num已经发生了变化!",newval,oldval);
}
}
})
}
</script>
</head>
<body>
<div id="app">
<p>{{ num }}</p>
<button @click="num++">按钮</button>
</div>
</body>
</html>
示例:用户名长度限制4-10位
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="js/vue.js"></script>
<script src="js/filters.js"></script>
</head>
<body>
<div id="app">
<form action="">
账号:<input type="text" v-model="form.username"><span :style="user_style">{{user_text}}</span><br><br>
密码:<input type="password" v-model="form.password"><br><br>
确认密码:<input type="password" v-model="form.password2"><br><br>
</form>
</div>
<script>
var vm1 = new Vue({
el:"#app",
data:{
form:{
username:"",
password:"",
password2:"",
},
user_style:{
color: "red",
},
user_text:"用户名长度只能是4-10位"
},
// 监听属性
// 监听属性的变化
watch:{
"form.username":function(value){ //注意,使用数据属性中的某个属性的时候,如果使用的是该数据中的内部属性,别忘了加双引号
if(value.length>=4 && value.length<=10){
this.user_style.color="blue";
this.user_text="用户名长度合法!";
}else{
this.user_style.color="red";
this.user_text="用户名长度只能是4-10位!";
}
}
}
})
</script>
</body>
</html>
3.3 vue对象的生命周期
前后端分离项目的简单过程:
前端在加载页面时,创建vm对象,圈地,渲染数据等步骤,每一个阶段都会自动触发一个钩子函数每个Vue对象在创建时都要经过一系列的初始化过程。在这个过程中Vue.js会自动运行一些叫做生命周期的的钩子函数,我们可以使用这些函数,在对象创建的不同阶段加上我们需要的代码,实现特定的功能。
课上测试:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Bootstrap 101 Template</title>
</head>
<body>
<div id="app">
<div>{{msg}}</div>
</div>
<script src="../vue.js"></script>
<script>
let vm = new Vue({
el: '#app',
data() {
return {
msg: '用户名不超过8位',
}
},
beforeCreate: function () { // vue对象创建了,地未圈,数据未加载。
console.log('beforeCreate方法')
console.log(this);
console.log(this.$el);
console.log(this.$data);
},
created: function () { // vue对象创建了,地未圈,数据已经加载,但是未渲染到地中。
console.log('create方法')
console.log(this);
console.log(this.$el);
console.log(this.$data);
},
mounted: function () { // vue对象创建了,圈地了,数据已经加载,渲染到地中。
console.log('mounted方法')
console.log(this);
console.log(this.$el);
console.log(this.$data);
}
})
</script>
</body>
</html>
所以,一般我们加载页面自动触发ajax向后端发送请求请求书时,这个ajax要写在created方法,有的人也会在mounted中构建。
笔记:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="js/vue.min.js"></script>
<script>
window.onload = function(){
var vm = new Vue({
el:"#app",
data:{
num:0
},
beforeCreate:function(){
console.log("beforeCreate,vm对象尚未创建,num="+ this.num); //undefined,就是说data属性中的值还没有放到vm对象中
this.name=10; // 此时没有this对象呢,所以设置的name无效,被在创建对象的时候被覆盖为0
console.log(this.$el) //undefined
},
created:function(){
// 用的居多,一般在这里使用ajax去后端获取数据,然后交给data属性
console.log("created,vm对象创建完成,设置好了要控制的元素范围,num="+this.num ); // 0 也就是说data属性中的值已经放到vm对象中
this.num = 20;
console.log(this.$el) //undefined
},
beforeMount:function(){
console.log( this.$el.innerHTML ); // <p>{{num}}</p> ,vm对象已经帮我们获取到了这个视图的id对象了
console.log("beforeMount,vm对象尚未把data数据显示到页面中,num="+this.num ); // 20,也就是说vm对象还没有将数据添加到我们的视图中的时候
this.num = 30;
},
mounted:function(){
// 用的居多,一般在这里使用ajax去后端获取数据然后通过js代码对页面中原来的内容进行更改
console.log( this.$el.innerHTML ); // <p>30</p>
console.log("mounted,vm对象已经把data数据显示到页面中,num="+this.num); // 30,也就是说vm对象已经将数据添加到我们的视图中的时候
},
// 后面两个简单作为了解吧,测试的时候最好单独测试下面两个方法
beforeUpdate:function(){
// this.$el 就是我们上面的el属性了,$el表示当前vue.js所控制的元素#app
console.log( this.$el.innerHTML ); // <p>30</p>
console.log("beforeUpdate,vm对象尚未把更新后的data数据显示到页面中,num="+this.num); // beforeUpdate----31
},
updated:function(){
console.log( this.$el.innerHTML ); // <p>31</p>
console.log("updated,vm对象已经把过呢更新后的data数据显示到页面中,num=" + this.num ); // updated----31
},
});
}
</script>
</head>
<body>
<div id="app">
<p>{{num}}</p>
<button @click="num++">按钮</button>
</div>
</body>
</html>
总结:
在vue使用的过程中,如果要初始化操作,把初始化操作的代码放在 mounted 中执行。
mounted阶段就是在vm对象已经把data数据实现到页面以后。一般页面初始化使用。例如,用户访问页面加载成功以后,就要执行的ajax请求。
另一个就是created,这个阶段就是在 vue对象创建以后,把ajax请求后端数据的代码放进 created
3.4 阻止事件冒泡和刷新页面
事件冒泡:父子标签都有相同的事件,我们触发子标签的事件时,会连同父标签一起触发。
课上测试:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Bootstrap 101 Template</title>
<style>
.c1 {
background-color: red;
width: 400px;
height: 400px;
}
.c2 {
background-color: blue;
width: 200px;
height: 200px;
}
</style>
</head>
<body>
<div id="app">
<div class="c1" @click="facli">
<div class="c2" @click.stop="soncli"></div>
</div>
</div>
<script src="../vue.js"></script>
<script>
let vm = new Vue({
el: '#app',
data() {
return {
msg: '用户名不超过8位',
}
},
methods: {
facli() {
alert('触发了父级事件!')
},
soncli() {
alert('触发了子级事件!')
}
}
})
</script>
</body>
</html>
使用.stop和.prevent
示例1:阻止事件冒泡
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
.box1{
width: 200px;
height: 200px;
background: #ccc;
}
.box2{
width: 100px;
height: 100px;
background: pink;
}
</style>
<script src="js/vue.min.js"></script>
<script>
window.onload = function(){
var vm = new Vue({
el:"#app",
data:{}
})
}
</script>
</head>
<body>
<div id="app">
<div class="box1" @click="show1('box1')">
<div class="box2" @click.stop="show2('box2')"></div> <!-- @click.stop来阻止事件冒泡,下面再加个prevent也可以 -->
<div class="box2" @click.stop.prevent="show2('box2')"></div>
</div>
<form action="#">
<input type="text">
<input type="submit">
<input type="submit" value="提交02" @click.prevent=""> <!-- @click.prevent来阻止表单提交,从而不刷新页面 -->
</form>
</div>
</body>
<script>
let vm = new Vue({
el:'#app',
data(){
return {
currentIndex:1,
'msg':'hello',
'price':200.1,
inp:'',
}
},
methods:{
show1(val){
console.log(val);
},
show2(val){
console.log(val);
}
}
})
</script>
</html>
示例2:阻止form表单提交动作
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="js/vue.js"></script>
<script src="js/filters.js"></script>
</head>
<body>
<div id="app">
<form action="">
账号:<input type="text" v-model="user"><br><br>
密码:<input type="password" v-model="pwd"><br><br>
<button @click.prevent="loginhander">登录</button>
</form>
</div>
<script>
var vm1 = new Vue({
el:"#app",
data:{
user:"",
pwd:"",
},
methods:{
loginhander(){
if(this.user.length<3 || this.pwd.length<3){
// 长度太短不能登录
alert("长度太短不能登录");
// 也可以写个return false; 也可以不写,prevent直接就是阻止form表单的提交动作
}else{
// 页面跳转
location.assign("http://www.baidu.com");
//或者:
//location.href="http://www.baidu.com";
}
}
}
})
</script>
</body>
</html>
3.5综合案例-todolist
我的计划列表
html代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>todolist</title>
<style type="text/css">
.list_con{
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 class="list_con">
<h2>To do list</h2>
<input type="text" name="" id="txt1" class="inputtxt">
<input type="button" name="" value="增加" id="btn1" class="inputbtn">
<ul id="list" class="list">
<!-- javascript:; # 阻止a标签跳转 -->
<li>
<span>学习html</span>
<a href="javascript:;" class="up"> ↑ </a>
<a href="javascript:;" class="down"> ↓ </a>
<a href="javascript:;" class="del">删除</a>
</li>
<li><span>学习css</span><a href="javascript:;" class="up"> ↑ </a><a href="javascript:;" class="down"> ↓ </a><a href="javascript:;" class="del">删除</a></li>
<li><span>学习javascript</span><a href="javascript:;" class="up"> ↑ </a><a href="javascript:;" class="down"> ↓ </a><a href="javascript:;" class="del">删除</a></li>
</ul>
</div>
</body>
</html>
答案:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>todolist</title>
<style type="text/css">
.list_con{
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>
<script src="vue.js"></script>
</head>
<body>
<div class="list_con">
<h2>To do list</h2>
<input type="text" name="" id="txt1" class="inputtxt">
<input type="button" name="" value="增加" id="btn1" class="inputbtn">
<ul id="list" class="list">
<!-- javascript:; # 阻止a标签跳转 -->
<li v-for="(val,index) in do_list" :key="val.id">
<span>{{ val.title }}</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>
<script>
let vm = new Vue({
el:'.list_con',
data(){
return {
dos:'',
do_list:[
{'id':1,'title':'学习html'},
{'id': 2, 'title': '学习css'},
{'id': 3, 'title': '学习js'},
],
}
},
methods:{
add(){
this.do_list.splice(index,1)
},
up(index){
if (index === 0){
return false
}
let del_ele = this.do_list.splice(index,1);
this.do_list.splice(index - 1,0,del_ele[0]);
},
del(index){
this.do_list.splice(index,1)
},
down(index){
let down_1 = this.do_list.splice(index,1);
this.do_list.splice(index+1,0,down_1[0]);
}
}
})
</script>
</body>
</html>
4. 通过axios实现数据请求
vue.js默认没有提供ajax功能的。
所以使用vue的时候,一般都会使用axios的插件来实现ajax与后端服务器的数据交互。
注意,axios本质上就是javascript的ajax封装,所以会被同源策略限制。
下载地址:
https://unpkg.com/axios@0.18.0/dist/axios.js
https://unpkg.com/axios@0.18.0/dist/axios.min.js
axios提供发送请求的常用方法有两个:axios.get() 和 axios.post() 。
增 post
删 delete
改 put
查 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);
});
// 发送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);
});
// b'firstName=Fred&lastName=Flintstone'
利用axios发送异步请求,请求天气预报的接口,获取响应数据。
我们想要使用axios需要下载axios的插件,后面框架给我们集成了axios源码功能,所以我们就不下载了,我们使用提供的网络源的axios。
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Bootstrap 101 Template</title>
</head>
<body>
<div id="app">
<!-- <h3>{{msg}}</h3>-->
<button @click="get_weather">获取北京的天气信息</button>
<h1 style="color: red">{{msg}}</h1>
</div>
<script src="../vue.js"></script>
<script src="https://unpkg.com/axios@0.18.0/dist/axios.min.js"></script>
<script>
let vm = new Vue({ // 创建一个vm对象
el: '#app', // 寻找标签的方式与css相同。 圈地,圈一片地,
// 可以做一些简单的js操作
data() {
return {
msg: '',
}
},
methods: {
get_weather(){
// 方式一
// let ths = this;
// console.log(this,11111)
// axios.get('http://wthrcdn.etouch.cn/weather_mini?city=北京').then(function (res) {
// // console.log(res)
// // console.log(res.data.data.ganmao)
// // console.log(this); // 这个是window对象
// ths.msg = res.data.data.ganmao;
// })
// 方式二: 通过箭头写法更改上下文
axios.get('http://wthrcdn.etouch.cn/weather_mini?city=北京').then((res) => {
// console.log(this) 这是这个this就是vm对象了
this.msg = res.data.data.ganmao;
})
}
}
})
</script>
</body>
</html>
课上测试:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Bootstrap 101 Template</title>
</head>
<body>
<div id="app">
<h3>{{weather_msg}}</h3>
<button @click="getWeather">获取北京天气情况</button>
</div>
<script src="../vue.js"></script>
<script src="https://unpkg.com/axios@0.18.0/dist/axios.min.js"></script>
<script>
// 1. 实例化一个vue对象
let vm = new Vue({
el: '#app', // 2 圈地,语法与css/jQuery查询标签的语言一样。
data() {
return {
weather_msg: '',
}
},
methods: {
getWeather() {
var ths = this;
axios.get('https://v0.yiketianqi.com/api?unescape=1&version=v91&appid=43656176&appsecret=I42og6Lm&ext=&cityid=&city=北京')
.then((response) => {
// 解决方式一
// console.log(response);
// console.log(response.data.city);
// console.log(this); // 箭头函数 获取的是上一级的对象
// this.weather_msg = response.data.city;
// 解决方式二
ths.weather_msg = response.data.city;
})
}
}
})
</script>
</body>
</html>
4.1 json
json是 JavaScript Object Notation 的首字母缩写,单词的意思是javascript对象表示法,这里说的json指的是类似于javascript对象的一种数据格式。
前后端需要数据交互,数据一旦通过网络传输就需要转化成bytes类型,而bytes类型的数据只能与字符串类型的数据互相转化,所以,我们应该将
list,dict等数据先 ---> str -----> bytes 发送 ----> 接收bytes ---> 解码str ---> 还原数据。
但是一般的str与(dict,list)数据不能相互转化,所以出现了json这种特殊的字符串(数据格式)。所有编程语言都承认这种json数据格式。
前端向后端发数据:
前端 数组[1, 2, 'barry'] ---> json数据格式(序列化) ----> bytes 使用JSON.stringify() 方法
后端 接收了bytes 数据 (解码)----> json数据格式 (反序列化)----> json.loads()
后端向前端发数据:
后端 数组[1, 2, 'barry'] ---> json数据格式(序列化) ----> bytes 使用json.dumps() 方法
前端 接收了bytes 数据 (解码)----> json数据格式 (反序列化)----> JSON.parse() 方法
json的作用:在不同的系统平台,或不同编程语言之间传递数据。
4.1.1 json数据的语法
json数据对象类似于JavaScript中的对象,但是它的键对应的值里面是没有函数方法的,值可以是普通变量,不支持undefined,值还可以是数组或者json对象。
// json数据的对象格式:
{
"name":"tom",
"age":18
}
// json数据的数组格式:
["tom",18,"programmer"]
复杂的json格式数据可以包含对象和数组的写法。
{
"name":"小明",
"age":200,
"fav":["code","eat","swim","read"],
"son":{
"name":"小小明",
"age":100,
"lve":["code","eat"],
}
}
// 数组结构也可以作为json传输数据。
json数据可以保存在.json文件中,一般里面就只有一个json对象。
总结:
1. json文件的后缀是.json
2. json文件一般保存一个单一的json数据
3. json数据的属性不能是方法或者undefined,属性值只能:数值、字符串、json和数组
4. json数据只使用双引号、每一个属性成员之间使用逗号隔开,并且最后一个成员没有逗号。
{
"name":"小明",
"age":200,
"fav":["code","eat","swim","read"],
"son":{
"name":"小小明",
"age":100
}
}
工具:postman可以用于测试开发的数据接口。
4.1.2 js中提供的json数据转换方法
javascript提供了一个JSON对象来操作json数据的数据转换.
方法 | 参数 | 返回值 | 描述 |
---|---|---|---|
stringify | 对象 | Json字符串 | 将一个对象转成json字符串(序列化) |
parse | Json字符串 | 对象 | 将json字符串还原回原对象 (反序列化) |
li = [11,233,44] python中的列表
str_json = json.dumps(li)
bytes_str_json = str_json.encode('utf-8') 发送
对方接受:bytes_str_json.decode('utf-8')
li = JSON.parse(str_json)
li 就是js中的数组
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<script>
// json语法
let humen = {
"username":"xiaohui",
"password":"1234567",
"age":20
};
console.log(humen);
console.log(typeof humen);
// JSON对象提供对json格式数据的转换功能
// stringify(json对象) # 用于把json转换成字符串
let result = JSON.stringify(humen);
console.log(result);
console.log(typeof result);
// parse(字符串类型的json数据) # 用于把字符串转成json对象
let json_str = '{"password":"1123","age":20,"name":"xiaobai"}';
console.log(json_str)
console.log(typeof json_str)
let json_obj = JSON.parse(json_str);
console.log(json_obj);
console.log(typeof json_obj)
console.log(json_obj.age)
</script>
</body>
</html>
4.2 ajax
ajax,一般中文称之为:“阿贾克斯”,是英文 “Async Javascript And Xml”的简写,译作:异步js和xml数据传输数据。
ajax的作用: ajax可以让js代替浏览器向后端程序发送http请求,与后端通信,在用户不知道的情况下操作数据和信息,从而实现页面局部刷新数据/无刷新更新数据。
所以开发中ajax是很常用的技术,主要用于操作后端提供的数据接口
,从而实现网站的前后端分离
。
ajax技术的原理是实例化js的XMLHttpRequest对象,使用此对象提供的内置方法就可以与后端进行数据通信。
4.2.1 数据接口
数据接口,也叫api接口,表示后端提供
操作数据/功能的url地址给客户端使用。
客户端通过发起请求向服务端提供的url地址申请操作数据【操作一般:增删查改】
同时在工作中,大部分数据接口都不是手写,而是通过函数库/框架来生成。
4.2.3 ajax的使用
ajax的使用必须与服务端程序配合使用,但是目前我们先学习ajax的使用,所以暂时先不涉及到服务端python代码的编写。因此,我们可以使用别人写好的数据接口进行调用。
jQuery将ajax封装成了一个函数$.ajax(),我们可以直接用这个函数来执行ajax请求。
接口 | 地址 |
---|---|
天气接口 | http://wthrcdn.etouch.cn/weather_mini?city=城市名称 |
音乐接口搜索 | http://tingapi.ting.baidu.com/v1/restserver/ting?method=baidu.ting.search.catalogSug&query=歌曲标题 |
音乐信息接口 | http://tingapi.ting.baidu.com/v1/restserver/ting?method=baidu.ting.song.play&songid=音乐ID |
编写代码获取接口提供的数据:
jQ版本
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="js/jquery-1.12.4.js"></script>
<script>
$(function(){
$("#btn").on("click",function(){
$.ajax({
// 后端程序的url地址
url: 'http://wthrcdn.etouch.cn/weather_mini',
// 也可以使用method,提交数据的方式,默认是'GET',常用的还有'POST'
type: 'get',
dataType: 'json', // 返回的数据格式,常用的有是'json','html',"jsonp"
data:{ // 设置发送给服务器的数据,如果是get请求,也可以写在url地址的?后面
"city":'北京'
},
// success:function(res){} 原版
})
.done(function(resp) { // 请求成功以后的操作,新的ajax是这样写的,之前是通过属性success:function(){}的形式来写的
console.log(resp);
})
.fail(function(error) { // 请求失败以后的操作
console.log(error);
});
});
})
</script>
</head>
<body>
<button id="btn">点击获取数据</button>
</body>
</html>
vue版本:
<!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">
<input type="text" v-model="city">
<button @click="get_weather">点击获取天气</button>
</div>
<script>
let vm = new Vue({
el:"#app",
data:{
city:"",
},
methods:{
get_weather(){
// http://wthrcdn.etouch.cn/weather_mini?city=城市名称
axios.get("http://wthrcdn.etouch.cn/weather_mini?city="+this.city)
.then(response=>{
console.log(response);
}).catch(error=>{
console.log(error.response)
});
}
}
})
</script>
</body>
</html>
总结:
1. 发送ajax请求,要通过$.ajax(),参数是对象,里面有固定的参数名称。
$.ajax({
"url":"数据接口url地址",
"method":"http请求方式,前端只支持get和post",
"dataType":"设置服务器返回的数据格式,常用的json,html,jsonp,默认值就是json",
// 要发送给后端的数据参数,post时,数据必须写在data,get可以写在data,也可以跟在地址栏?号后面
"data":{
"数据名称":"数据值",
}
}).then(function(resp){ // ajax请求数据成功时会自动调用then方法的匿名函数
console.log( resp ); // 服务端返回的数据
}).fail(function(error){ // ajax请求数据失败时会自动调用fail方法的匿名函数
console.log( error );
});
2. ajax的使用往往配合事件/钩子操作进行调用。
jQuery还提供了$.get 和 $post简写$.ajax的操作。
// 发送get请求
// 参数1:数据接口的请求地址
// 参数2:发送给接口地址的数据参数
// 参数3:ajax请求成功以后,调用的匿名函数,匿名函数的第一个参数还是服务端返回的数据
// 参数4:设置服务端返回的数据格式,告诉给jQuery
$.get("test.php", { "func": "getNameAndTime" },
function(data){
alert(data.name); // John
console.log(data.time); // 2pm
}, "json");
// 发送post请求
// 参数1:数据接口的请求地址
// 参数2:发送给接口地址的数据参数
// 参数3:ajax请求成功以后,调用的匿名函数,匿名函数的第一个参数还是服务端返回的数据
// 参数4:设置服务端返回的数据格式,告诉给jQuery
$.post("test.php", { "func": "getNameAndTime" },
function(data){
alert(data.name); // John
console.log(data.time); // 2pm
}, "json");
4.2.4 同源策略
同源策略,是浏览器为了保护用户信息安全的一种安全机制。所谓的同源就是指代通信的两个地址(例如服务端接口地址与浏览器客户端页面地址)之间比较,是否协议、域名(IP)和端口相同。不同源的客户端脚本[javascript]在没有明确授权的情况下,没有权限读写对方信息。
ajax本质上还是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 | 否 | 域名不同 ( bbs和www ) |
同源策略针对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.
上面错误,关键词:Access-Control-Allow-Origin
只要出现这个关键词,就是访问受限。出现同源策略的拦截问题。
4.2.5 ajax跨域(跨源)方案之CORS
CORS是一个W3C标准,全称是"跨域资源共享",它允许浏览器向跨源的后端服务器发出ajax请求,从而克服了AJAX只能同源使用的限制。
实现CORS主要依靠后端服务器中响应数据中设置响应头信息返回的。
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: *
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wDCpA7v1-1677068813230)(F:\newschool\上课笔记\vue笔记\day03\assets\1556074087897.png)]
总结:
0. 同源策略:浏览器的一种保护用户数据的一种安全机制。
浏览器会限制脚本语法不能跨源访问其他源的数据地址。
同源:判断两个通信的地址之间,是否协议,域名[IP],端口一致。
ajax: http://127.0.0.1/index.html
api数据接口: http://localhost/index
这两个是同源么?不是同源的。是否同源的判断依据不会根据电脑来判断,而是通过协议、域名、端口的字符串是否来判断。
1. ajax默认情况下会受到同源策略的影响,一旦受到影响会报错误如下:
No 'Access-Control-Allow-Origin' header is present on the requested resource
2. 解决ajax只能同源访问数据接口的方式:
1. 在服务端的响应行中设置:
Access-Control-Allow-Origin: 允许访问的域名地址
2. jsonp
3. 是否服务端代理
思路:通过python来请求对应的服务器接口,获取到数据以后,
5. 组件化开发
5.1 组件[component]
组件(Component)是自定义封装的功能。在前端开发过程中,经常出现多个网页的功能是重复的,而且很多不同的网站之间,也存在同样的功能。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7uFw6cBy-1677068813231)(F:\newschool\上课笔记\vue笔记\day03\assets\image-20200708173439538.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-52N5URKz-1677068813232)(F:\newschool\上课笔记\vue笔记\day03\assets\image-20200708173453716.png)]
而在网页中实现一个功能,需要使用html定义功能的内容结构,使用css声明功能的外观样式,还要使用js来定义功能的特效,因此就产生了把一个功能相关的[HTML、css和javascript]代码封装在一起组成一个整体的代码块封装模式,我们称之为“组件”。
vue框架更倾向于使用SPA这种模式,single page application,单页面应用开发。
我们只有一个html页面,不同的url对应的不同的页面,其实就是在单个html页面上,进行不同的各种组件的替换。这种的优势两点:
- 减少重复代码的使用。(不用创建很多html,公共的组件可以用一个,比如顶部导航栏)
- 提升页面的加载效率。(对于与前后端未分离的项目【渲染整个html页面,完毕之后,在发送给浏览器】,浏览器接收到这个渲染之后的页面,有可能还会触发各种ajax请求或者其他的请求,然后在进行后端请求数据)
组件化开发比django好在哪?
-
如果你的页面有很多数据请求,比如京东首页,会大量的请求后端的数据,图片等数据,我们通过render渲染这样就会出现白屏效应。
-
组件化开发,每个组件都可以发送异步请求,这样会极大的提升你的效率。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-69hDHpAn-1677068813239)(F:\newschool\上课笔记\vue笔记\day03\assets\image-20200708175007685.png)]
所以,组件就是一个html网页中的功能,一般就是一个标签,标签中有自己的html内容结构,css样式和js特效。
这样,前端人员就可以在开发时,只需要书写一次代码,随处引入即可使用。
我们在进行vue开发的时候,还记得我们自己创建的vm对象吗,这个vm对象我们称为一个大组件,根组件(页面上叫Root),在一个网页的开发中,根据网页上的功能区域我们又可以细分成其他组件,或称为子组件
组件有两种:默认组件[全局组件] 和 单文件组件[局部组件]
局部组件:需要依赖于某个父级组件,挂载到父级附件上展示。
全局组件:项目的各个页面都会使用的组件,公共的组件。
5.1.1局部组件
三步:声子、用子、挂子
组件与vm对象用法几乎一样,除了圈地属性不使用,其他的属性都具备。
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Bootstrap 101 Template</title>
</head>
<body>
<div id="app">
<!-- 3. 用子 -->
<!-- <App></App>-->
<App/>
</div>
<script src="../vue.js"></script>
<script>
// 1. 声子, 声明组件
let App = {
data(){
return {
msg: 'app组件的数据',
}
},
template:
`
<div class="app">
{{msg}}
</div>
`
};
let vm = new Vue({
el: '#app',
data() {
return {}
},
components: {
// App: App,
App, // 简写 2. 挂子 将app组件挂载到vm对象上。
}
})
</script>
</body>
</html>
5.1.2 默认组件(全局组件)
直接看代码,局部组件使用时需要挂载,全局组件使用时不需要挂载。那么他们两个什么时候用呢,局部组件就在某个局部使用的时候,全局组件是大家公用的,或者说每个页面都有这么一个功能的时候,在哪里可能都会用到的时候。
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Bootstrap 101 Template</title>
</head>
<body>
<div id="app">
<Vv/>
</div>
<script src="../vue.js"></script>
<script>
// 全局组件
Vue.component('Vv', {
data() {
return {
msg1: '全剧组件vv数据',
}
},
template:
`
<div class="vv">
{{msg1}}
</div>
`
});
let vm = new Vue({
el: '#app',
data() {
return {}
},
})
</script>
</body>
</html>
5.2 组件传值
通过prop属性进行传值
5.2.1 父组件往子组件传值
两步:
- 在父组件模版中,引用子组件标签中定义传递数据的属性以及属性值。
- 在子组件中定义props方法,罗列引用的数据的属性名,在子组件的模版中,渲染此属性名。
看示例:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Bootstrap 101 Template</title>
</head>
<body>
<div id="app">
<App></App>
</div>
<script src="../vue.js"></script>
<script>
let Vheader = {
data() {
return {
vheader_msg: 100,
}
},
template:
`
<div class="vheader">
{{vheader_msg}}
父组件传递的值:{{xx}}
</div>
`,
props: ['xx',],
};
// 1. 声子, 声明组件
let App = {
data() {
return {
msg: 'app组件的数据',
fa_num: 40,
}
},
template:
`
<div class="app">
{{msg}}
<Vheader :xx="fa_num"></Vheader>
</div>
`,
components: {
Vheader,
}
};
let vm = new Vue({
el: '#app',
data() {
return {}
},
components: {
// App: App,
App, // 简写 2. 挂子 将app组件挂载到vm对象上。
}
})
</script>
</body>
</html>
使用父组件传递数据给子组件时, 注意一下几点:
-
传递数据是变量,则需要在属性左边添加冒号.
传递数据是变量,这种数据称之为"动态数据传递"
传递数据不是变量,这种数据称之为"静态数据传递"
-
父组件中修改了数据,在子组件中会被同步修改,但是,子组件中的数据修改了,是不是影响到父组件中的数据.
这种情况,在开发时,也被称为"单向数据流"
5.2.2 子组件父组件传值
两步:
a. 子组件中使用this.$emit(‘fatherHandler’,val);fatherHandler是父组件中使用子组件的地方添加的绑定自定义事件,注意,如果fatherHandler报错了,那么可能是你的vue版本不支持自定义键名称fatherHandler中有大写字母,所以我们改成father-handler或者直接就全部小写就可以了
<Vheader @fatherHandler="appFatherHandler"></Vheader>
b.父组件中的methods中写一个自定义的事件函数:appFatherHandler(val){},在函数里面使用这个val,这个val就是上面子组件传过来的数据
看代码:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Bootstrap 101 Template</title>
</head>
<body>
<div id="app">
<App></App>
</div>
<script src="../vue.js"></script>
<script>
let Vheader = {
data() {
return {
vheader_msg: 100,
to_fa: '养老送终',
}
},
template:
`
<div class="vheader">
{{vheader_msg}}
<button @click="toFather">走你</button>
</div>
`,
methods: {
toFather(){
this.$emit('func',this.to_fa)
}
}
};
// 1. 声子, 声明组件
let App = {
data() {
return {
from_son: '',
}
},
template:
`
<div class="app">
来自儿子的数据:{{from_son}}
<Vheader @func="recv_son_data"></Vheader>
</div>
`,
methods :{
recv_son_data(val){
this.from_son = val;
}
} ,
components: {
Vheader,
}
};
let vm = new Vue({
el: '#app',
data() {
return {}
},
components: {
// App: App,
App, // 简写 2. 挂子 将app组件挂载到vm对象上。
}
})
</script>
</body>
</html>
5.2.3 平行组件传值
借助“bus公交车”。
什么是平行组件,看图
看代码 :声明两个全局组件T1和T2,T1组件将数据传送给T2组件
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Bootstrap 101 Template</title>
</head>
<body>
<div id="app">
<App></App>
</div>
<script src="../vue.js"></script>
<script>
// 公交车
let bus = new Vue();
let t1 = {
data() {
return {
msg: 't1的数据',
to_t2: '给t2传递的数据!!!',
}
},
template: `
<div class="t1">
<h1>{{msg}}</h1>
<button @click="toT2">走你</button>
</div>
`,
methods: {
toT2(){
bus.$emit('tot2data',this.to_t2);
}
}
};
let t2 = {
data() {
return {
msg: '',
}
},
template: `
<div class="t2">
<h1>{{msg}}</h1>
</div>
`,
created(){
bus.$on('tot2data',(val)=>{
this.msg = val;
})
}
};
// 1. 声子, 声明组件
let App = {
data() {
return {}
},
template:
`
<div class="app">
<t1></t1>
<t2></t2>
</div>
`,
methods: {},
components: {
t1,
t2,
}
};
let vm = new Vue({
el: '#app',
data() {
return {}
},
components: {
// App: App,
App, // 简写 2. 挂子 将app组件挂载到vm对象上。
}
})
</script>
</body>
</html>