Vue
实例与容器关联Vue模板
{{}}
中写的是js表达式
,可以读取到data
中的所有属性代码:
<script src="../js/vue.js" type="text/javascript" charset="utf-8">script>
<div id="root">
<h1>{{name.toUpperCase()}}h1>
div>
<script>
Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示
//2. 创建Vue实例
new Vue({
el:'#root',
data:{
"name":"Hello world"
}
})
script>
{{js表达式}}
,可以直接读取data
中的所有属性v-vbind:href="js表达式"
或简写为:href="js表达式"
,可以直接读取data
中的所有属性Vue
中有很多指令,此处只是拿v-bind
举例<div id="root">
<h1>插值语法h1>
<h3>Hello , {{name}}h3>
<hr />
<h1>指令语法h1>
<a v-bind:href="url">百度1a>
<a :href="url">百度2a>
div>
<script>
new Vue({
el:'#root',
data:{
name:'world',
url:'https://www.baidu.com'
}
})
script>
Vue
中有两种数据绑定方式:
v-bind
):数据只能从data
流向页面v-model
):数据不仅能从data
流向页面,也能从页面流向data
v-model:value
可以简写为v-model
,因为v-model
默认收集的就是value
的值。代码:
<div id="root">
单项数据绑定:<input type="text" v-bind:value="name">
双向数据绑定:<input type="text" v-model:value="age">
div>
<script type="text/javascript">
const vm = new Vue({ //可以通过控制台操作vue实例,设置或获取name、age的值,观察他们的区别
el:'#root',
data:{
name:"zhangsan",
age:23
}
})
script>
el
的作用:绑定模板
new Vue
时候配置el
属性Vue
实例,随后再通过vm.$mount('#root')
指定el
表达式//方式一
const vm = new Vue({
el:'#root'
})
//方式二
vm.$mount('#root')
data
的作用:将数据交给Vue
实例管理
data
必须使用函数式。否则会报错//1. 对象式
const vm = new Vue({
data:{
name:"zhangsan",
age:23
}
})
//2. 函数式一
const vm = new Vue({
data:function(){
return {
name:'Hello world!'
}
}
})
//3. 函数式二
const vm = new Vue({
data(){
return {
name:'Hello world!'
}
}
})
M
:模型(Model
):data
中的数据V
:视图(View
):模板代码VM
:视图模型(ViewMode
):Vue
实例观察发现:
data
中所有的属性,最后都出现在了vm
身上vm
身上所有的属性及Vue
原型上所有的属性。在Vue模板
都可以直接使用javascript
原生的数据代理使用函数Object.defineProperty
实现
向person对象
中添加属性,并控制该属性可以被枚举,可以被修改,可以被删除
let person = {
name:'张三',
sex:'男'
}
Object.defineProperty(person,'age',{
value:23,
enumerable:true, //控制属性可以被枚举(遍历),默认值是false
writable:true, //控制属性可以被修改,默认值false
configurable:true //控制属性可以被删除,默认false
})
console.log(Object.keys(person)) //拿到属性所有的key
for(let key in person){ //遍历person的属性
console.log(person[key])
}
//删除age
delete person.age
当修改变量num
的值时,对应的person.age
也会发生变化,修改person.age
的值时,num
也会发生变化
let num = 23;
let person = {
name:'张三',
sex:'男'
}
//全写
Object.defineProperty(person,'age',{
get:function(){ //当有人读取person的age属性时,get函数就会被调用,且返回age的值
console.log('有人读取了age值')
return num;
},
set:function(value){ //当有人通过person对象修改属性age的值时,set函数就会被调用,且会收到修改的具体值
console.log('有人设置了age值')
num = value
}
})
//简写
Object.defineProperty(person2,'age',{
get(){
console.log('有人读取了age值')
return num;
},
set(value){
console.log('有人设置了age值')
num = value
}
})
把data
上的数据放代理一份到vm对象
上,实现修改data
就能修改vm
上的数据,修改vm
就能修改data
中的数据的效果,目的是为了让编码更方便
Vue
中的数据代理:vm
对象来代理data
对象中的属性的操作(读/写)Vue
中数据代理的好处:data
中的数据Object.defineProperty()
把data对象
中所有属性添加到vm
上。vm
上的属性,都指定一个get/set
get/set
内部操作读/写data
中对应的属性v-on:xxx
或者@xxx
绑定事件methods
对象中,最终会在vm
对象上methods
中配置函数,不要使用箭头函数,否则this
就不是vm
了methods
中配置函数,都是被Vue
所管理的函数,this
的指向是vm或组件实例对象
@click="demo"
和 @click="demo($event)"
效果一致,但后者可以传参 <div id="root">
<h2>{{name}},欢迎您!h2>
<button type="button" v-on:click="showInfo1">点我提示信息1(不传参)button>
<button type="button" @click="showInfo2($event,66)">点我提示信息2(传参)button>
div>
<script type="text/javascript">
//全写
new Vue({
el:'#root',
data:{
name:'张三'
},
methods:{
showInfo1:function(event){ //参数默认是事件的参数
console.log(event)
alert('点我提示信息1')
},
showInfo2:function(event,id){
console.log(event)
alert(id)
}
}
})
//简写
new Vue({
el:'#root',
data:{
name:'张三'
},
methods:{
showInfo1(event){ //参数默认是事件的参数
console.log(event)
alert('点我提示信息1')
},
showInfo2(event,id){
console.log(event)
alert(id)
}
}
})
script>
Vue
中的事件修饰符
prevent
:阻止默认事件(常用)
stop
:阻止事件冒泡(常用)
once
:事件只触发一次(常用)
capture
:使用事件的捕获模式
self
:只有event.target
是当前操作的元素时才会触发事件
passive
:事件的默认行为立即执行,无需等待事件回调执行完毕
<div id="root">
<a href="https://www.baidu.com" @click.prevent="showInfo1">点我提示信息1a>
<div class="demo1" @click="showInfo1">
<button @click.stop="showInfo1">点我提示信息1button>
div>
<div class="demo1" @click="showInfo1">
<a href="https://www.baidu.com" @click.prevent.stop="showInfo1">点我提示信息1a>
div>
<button type="button" @click.once="showInfo1">点我提示信息1button>
<div class="box1" @click.capture="showInfo2(1)">box1
<div class="box2" @click="showInfo2(2)">box2div>
div>
<div class="box1" @click.self="showInfo2(1)">box1
<div class="box2" @click.self="showInfo2(2)">box2div>
div>
<ul class="list" @mousewheel.passive="demo">
<li>1li>
<li>2li>
<li>3li>
<li>4li>
<li>5li>
<li>6li>
ul>
div>
<script type="text/javascript">
new Vue({
el:'#root',
methods:{
showInfo1(){
alert('点我提示信息1')
},
showInfo2(index){
alert(index)
},
demo(){
for(let i = 0; i < 100000;i++){
console.log('@')
}
}
}
})
script>
Vue
常用的按键别名:
回车 => enter
删除或退格 => delete
退出 => esc
空格 => space
换行 => tab(特殊,必须配合keydown事件才能使用,否则使用keyup的话,未等触发事件,事件焦点就会消失,因为浏览器有一个自动切换焦点的快捷键就是tab)
上 => up
下 => down
左 => left
右 => right
Vue
未提供别名的按键,可以使用按键原始的Key
值去绑定,但注意如果key
是由多个单词组成
,需要转换,例如CapsLock -> caps-lock
系统修饰键(用法特殊):ctrl,alt,shift,meta
keyup
使用:按下修饰键的同时,再按下其他键,随后释放其他键,事件才被触发(一般使用组合键模式)keydown
使用:正常触发事件<div id="root">
<input type="text" @keyup.enter="showInfo">
<input type="text" @keyup.ctrl.y="showInfo">
div>
<script type="text/javascript">
new Vue({
el:'#root',
methods:{
showInfo(event){
console.log(event.key,event.keyCode) //输出按键的名称和编码
console.log(event.target.value) //输出事件当前操作的元素的值
}
}
})
script>
计算属性:
Object.defineproperty
方法提供的get和set
get
函数什么时候执行:
methods
实现相比,内部有缓存机制(复用),效率更高,调试方便vm
上,直接调用即可set
函数去响应修改。且set
函数中要引起被依赖的数据发生变化姓 + 名
案例:
<div id="root">
姓:<input type="text" v-model="firstName"> <br><br>
名:<input type="text" v-model="lastName" /> <br><br>
姓名:<input type="text"v-model="fullName">
div>
<script type="text/javascript">
//全写
new Vue({
el:'#root',
data:{
firstName:'张',
lastName:'三'
},
computed:{ //计算属性
fullName:{
get(){
return this.firstName + '-' + this.lastName
},
set(value){
const arr = value.split('-')
this.firstName = arr[0]
this.lastName = arr[1]
}
}
}
})
//简写
new Vue({
el:'#root',
data:{
firstName:'张',
lastName:'三'
},
computed:{ //计算属性
fullName(){ //注意:这种简写仅适用于不需要对计算属性进行修改的情况,也就说不需要写set方法的情况
return this.firstName + '-' + this.lastName
}
}
})
script>
监视属性watch
new Vue
时传入watch
配置vm.$watch
监视 <div id="root">
<input type="text" v-model="name">
div>
<script type="text/javascript">
//全写
const vm = new Vue({
el:'#root',
data:{
name:'张三'
},
watch:{
name:{ //监视属性:name
immediate:true, //初始化时让handler调用一下,默认值false
handler(newValue,oldValue){
console.log(newValue,oldValue)
}
}
}
})
//写法2
vm.$watch('name',{
immediate:true, //初始化时让handler调用一下,默认值false
handler(newValue,oldValue){
console.log(newValue,oldValue)
}
})
//简写(注意:如果需要设置监视属性,如immediate、deep,则不能使用简写)
new Vue({
el:'#root',
data:{
name:'张三'
},
watch:{
name(newValue,oldValue){
console.log(newValue,oldValue)
}
}
})
script>
Vue
中的watch
默认不监视对象内部值的变化deep:true
可以监视对象内部值的变化备注:
Vue
自身可以监视对象内部值的变化,但Vue
提供的watch
默认不可以watch
时根据数据的具体结构,决定是否采用深度监视<div id="root">
<h3>a的值是{{number.a}}h3>
<button type="button" @click="number.a++">点我让a+1button>
<h3>b的值是{{number.b}}h3>
<button type="button" @click="number.b++">点我让b+1button>
div>
<script type="text/javascript">
new Vue({
el:'#root',
data:{
number:{
a:1,
b:1
}
},
watch:{
'number.a':{ //监视对象如果有特殊字符,如点,可以采用这种方式监视
handler(){
console.log('a的值发生了改变')
}
},
'number.b':{
handler(){
console.log('b的值发生了改变')
}
},
number:{
deep:true, //开启深度监视
handler(){
console.log('number的值发生了改变')
}
}
}
})
script>
:class="xxx" xxx
可以是字符串、对象、数组style
样式::style="xxx" xxx
可以是字符串、对象、对象数组<head>
<style type="text/css">
.basic{
}
.happy{
}
.sad {
}
.normal{
}
.box1{
}
.box2{
}
.box3{
}
style>
head>
<body>
<div id="root">
<div class="basic" :class="mood" @click="changeMood">{{name}}div> <br><br>
<div class="basic" :class="classArr">{{name}}div> <br><br>
<div class="basic" :class="classObj">{{name}}div>
<div class="basic" :style="styleObj">{{name}}div>
<div class="basic" :style="[styleObj,styleObj2]">{{name}}div>
div>
<script type="text/javascript">
new Vue({
el:'#root',
data:{
name:'张三',
mood:'normal',
classArr:['box1','box2','box3'],
classObj:{
box1:true,
box2:true,
box3:true
},
styleObj:{
fontSize:'40px', //注意:多个单词的样式需要转为驼峰式,比如font-size -> fontSize
color:'red',
backgroundColor: '#f7aa28'
},
styleObj2:{
borderRadius: '10%'
}
},
methods:{
changeMood(){
const moodArr = ['happy','sad','normal']
const index = Math.floor(Math.random() * moodArr.length)
this.mood = moodArr[index]
}
}
})
script>
body>
v-if
1. v-if="布尔表达式"
2. v-else-if="布尔表达式"
3. v-else
适用于:切换频率较低的场景DOM
元素,直接移除v-if
和v-else-if
和v-else
组合使用时,要求结构不能被打断template
标签配套v-if
指令可以去除一堆结构,并且template
没有任何意义,不会影响页面的DOM
结构v-show
v-show="布尔表达式"
DOM
元素,底层使用样式display:none
隐藏v-if
时,元素将无法被获取,因为被移除了,而使用v-show
一定可以获取到<div id="root">
<h2>n的值:{{n}}h2>
<button type="button" @click="n++">点我n+1button>
<h2 v-show="false">张三h2>
<h2 v-show="1 === 1">张三h2>
<h2 v-show="isShow">张三h2>
<hr />
<h2 v-if="n===24">李四h2>
<h2 v-if="n===25">王五h2>
<h2 v-if="n===26">赵六h2>
<hr />
<h2 v-if="n===24">李四h2>
<h2 v-else-if="n===25">王五h2>
<h2 v-else>赵六h2>
<hr />
<template v-if="n===1">
<h2>李四h2>
<h2>王五h2>
<h2>赵六h2>
template>
div>
<script type="text/javascript">
new Vue({
el:'#root',
data:{
isShow:true,
n:0
}
})
script>
v-for
指令:
v-for="(item,index) in xxx" :key="yyy"
<div id="root">
<h2>人员列表h2>
<ul><li v-for="(item,index) in persons" :key="item.id">{{index + 1}}--{{item.name}}-{{item.age}}li>ul>
<h2>人员列表h2>
<ul><li v-for="item of persons" :key="item.id">{{item.name}}-{{item.age}}li>ul>
<hr>
<h2>汽车信息h2>
<ul><li v-for="(item,key) in car" :key="key">{{key}}-{{item}}li>ul>
<hr>
<h2>字符串h2>
<ul>
<li v-for="(item,index) in str" :key="index">
{{index}}-{{item}}
li>
ul>
<hr>
<h2>遍历指定次数h2>
<ul>
<li v-for="(item,index) in 5" :key="index">
{{index}}-{{item}}
li>
ul>
div>
<script type="text/javascript">
new Vue({
el:'#root',
data:{
persons:[
{
"id":"001",
"name":"张三",
"age":23
},
{
"id":"002",
"name":"李四",
"age":24
},
{
"id":"003",
"name":"王五",
"age":25
}
],
car:{
"id":"c001",
"name":"奔驰",
"price":"28万"
},
str:'hello'
}
})
script>
vue
中的key
有什么作用?(key
的内部原理):
DOM
中key
的作用:key
是虚拟DOM
对象的标识,当数据发生变化时,Vue
会根据【新数据】生成【新的虚拟DOM
】,随后Vue
进行【新虚拟DOM
】与【旧虚拟DOM
】的差异比较,比较规则如下:DOM
中找到了与新虚拟DOM
相同的keyDOM
中内容没变,直接使用之前的真实DOM
DOM
中内容变了,则生成新的真实DOM
,随后替换掉页面中之前的真实DOM
.DOM
中未找到与新虚拟DOM
相同的key
DOM
,随后渲染到到页面。index
作为key
可能会引发的问题:DOM
更新==>界面效果没问题,但效率低。DOM
:会产生错误DOM
更新==>界面有问题。key
?key
,比如id
、手机号、身份证号、学号等唯一值
index
作为key
是没有问题的。涉及技术:
javascript
基础
filter
:过滤数组函数indexOf
:字符串包含函数Vue
技术
使用监视属性做
<div id="root">
<h2>学生信息h2>
<input type="text" placeholder="请输入关键词" v-model="keyword">
<ul>
<li v-for="item in filterPersons" :key="item.id">{{item.name}}-{{item.age}}-{{item.sex}}li>
ul>
div>
<script type="text/javascript">
new Vue({
el:'#root',
data:{
keyword:'',
persons:[
{
"name":"马冬梅",
"age":19,
"sex":"女"
},
{
"name":"周冬雨",
"age":20,
"sex":"女"
},
{
"name":"周杰伦",
"age":21,
"sex":"男"
},
{
"name":"温兆伦",
"age":22,
"sex":"男"
}
],
filterPersons:[]
},
watch:{
keyword:{
immediate:true,
handler(val){
this.filterPersons = this.persons.filter((item)=>{
return item.name.indexOf(val) != -1;
})
}
}
}
})
script>
使用计算属性做
<div id="root">
<h2>学生信息h2>
<input type="text" placeholder="请输入关键词" v-model="keyword">
<ul>
<li v-for="item in filterPersons" :key="item.id">{{item.name}}-{{item.age}}-{{item.sex}}li>
ul>
div>
<script type="text/javascript">
new Vue({
el:'#root',
data:{
keyword:'',
persons: ['上面已有,这边不重复展示。']
},
computed:{
filterPersons(){
return this.persons.filter((item)=>{
return item.name.indexOf(this.keyword) != -1
})
}
}
})
script>
涉及技术:
javascript
基础
sort
:数组排序函数if
判断中,0
默认转为false
Vue
技术
<div id="root">
<h2>学生信息h2>
<button type="button" @click="sort=1">按照年龄升序button>
<button type="button" @click="sort=2">按照年龄降序button>
<button type="button" @click="sort=0">按照原顺序button>
<ul>
<li v-for="item in filterPersons" :key="item.id">{{item.name}}-{{item.age}}-{{item.sex}}li>
ul>
div>
<script type="text/javascript">
new Vue({
el:'#root',
data:{
sort:0,
persons: ['上面已有,这边不重复展示。']
},
computed:{
filterPersons(){
const arr = this.persons;
if(this.sort){
arr.sort((p1,p2)=>{
if(this.sort == 1){
return p2.age - p1.age
}else{
return p1.age - p2.age
}
})
}
return arr
}
}
})
script>
问题:Vue
监测不到数组里对象整体替换发生改变的情况
解答:
Vue
对于对象和数组的监测方式:
Vue
对于对象里面的元素的监听是get
和set
方法(判断Vue
里的一个对象是否是响应式,只需判断有没有对应的get
和set
)Vue
对于数组的监听的是数组的七个方法:
push
pop
shift
unshift
splice
sort
reverse
注意:修改数组元素,绝对不能用下标索引去修改
<div id="root">
<h2>学生信息h2>
<button type="button" @click="updateMei">修改马冬梅的信息button>
<ul>
<li v-for="item in persons" :key="item.id">{{item.name}}-{{item.age}}-{{item.sex}}li>
ul>
div>
<script type="text/javascript">
const vm = new Vue({
el:'#root',
data:{
persons:['上面已有,这边不重复展示。']
},
methods:{
//修改数组中对象的属性(Vue可以监测)
updateMei(){
this.persons[0].name = '马老师'
this.persons[0].age = 50
this.persons[0].sex = '男'
}
//修改数组中整个对象(Vue无法监测)
updateMei(){
this.persons[0] = {
"name":"马老师",
"age":50,
"sex":"男"
};
}
//使用数组函数修改数组中整个对象(Vue可以监测)
updateMei(){
this.persons.splice(0,1,{
"name":"马老师",
"age":50,
"sex":"男"
})
}
}
})
script>
Vue
追加响应式属性:Vue.set(target,propertyName/index,value)
或vm.$set(target,propertyName/index,value)
注意:
Vue
不能给vm
或vm
的根数据对象添加属性,即target
不能等于vm
或指代vm
的this
,但是可以给data
中的数组或对象进行修改或新增属性。
<div id="root">
<h2>学生信息h2>
<button type="button" @click="addSex">点我给学生添加一个性别button>
<ul>
<li v-for="item in persons" :key="item.id">
<ul>
<li>学生姓名:{{item.name}}li>
<li>学生年龄:{{item.age}}li>
<li v-show="item.sex">学生性别:{{item.sex}}li>
ul>
li>
ul>
div>
<script type="text/javascript">
const vm = new Vue({
el:'#root',
data:{
persons:['上面已有,这边不重复展示。']
},
methods:{
addSex(){
this.$set(this.persons[0],'sex','女')
this.$set(this.persons[1],'sex','女')
this.$set(this.persons[2],'sex','男')
this.$set(this.persons[3],'sex','男')
}
}
})
script>
v-model
收集的是value
值,像radio
、checkbox
这些没有value
值的,默认收集的是true|false
,我们需要手动加上value
属性,让他收集我们指定的值checkbox
如果有多个,需要对对应的v-model
属性设置为数组,否则他依然默认收集的是true|false
@submit
事件v-model
修饰符:
lazy
:失去焦点再收集数据,一般用于数据量比较大的文本框number
:输入为字符串转为数字,一般跟
配套使用trim
:去除首位空格<div id="root">
<form @submit.prevent="demo">
账号:<input type="text" name="account" v-model.trim="userInfo.account"> <br>
密码:<input type="password" name="password" v-model.trim="userInfo.password"> <br>
年龄:<input type="number" name="age" v-model.number="userInfo.age"> <br>
性别:男<input type="radio" name="sex" v-model="userInfo.sex" value="man">
女<input type="radio" name="sex" v-model="userInfo.sex" value="woman"><br>
爱好:学习<input type="checkbox" name="hobby" v-model="userInfo.hobby" value="study">
打游戏<input type="checkbox" name="hobby" v-model="userInfo.hobby" value="play">
吃饭<input type="checkbox" name="hobby" v-model="userInfo.hobby" value="eat"> <br>
所属校区:<select name="school" v-model="userInfo.school">
<option value ="">--请选择--option>
<option value="beiJing">北京option>
<option value="shangHai">上海option>
<option value="chongQing">重庆option>
select><br>
其他信息:<textarea rows="5" cols="20" name="other" v-model.lazy.trim="userInfo.other">textarea><br>
<input type="checkbox" name="agree" v-model="userInfo.agree">阅读并接受<a href="http://www.baidu.com">用户协议a><br>
<input type="submit" value="提交">
form>
div>
<script type="text/javascript">
new Vue({
el:'#root',
data:{
userInfo:{
account:'',
password:'',
age:15,
sex:'',
hobby:[],
school:'beiJing',
other:'',
agree:false
}
},
methods:{
demo(){
console.log(JSON.stringify(this.userInfo))
}
}
})
script>
定义:对需要展示的数据进行特定的逻辑处理再展示
语法:
Vue.filter(name,callback)
Vue
实例中使用)new Vue(filters:{})
{{xxx | 过滤器1 | 过滤器2...}}
或 v-bind:属性="xxx | 过滤器1 | 过滤器2..."
;注意:v-model
不能使用过滤器。下面代码使用了:dayjs.min.js
库,来源:BootCDN:https://www.bootcdn.cn/
<body>
<div id="root">
<h2>显示格式化后的时间h2>
<h3>计算属性:现在是:{{nowTime1}}h3>
<h3>methods实现:现在是:{{nowTime2()}}h3>
<h3>过滤器实现:现在是:{{time | nowTime3}}h3>
<h3>过滤器传参实现:今日是:{{time | nowTime3('YYYY/MM/DD')}}h3>
<h3>过滤器串联实现:今年是:{{time | nowTime3('YYYY/MM/DD') | nowTime3('YYYY')}}h3>
div>
<script type="text/javascript">
Vue.filter('nowTime3',function(val,format='YYYY-MM-DD HH:mm:ss'){
return dayjs(val).format(format)
})
new Vue({
el:'#root',
data:{
time:Date.now()
},
computed:{
nowTime1(){
return dayjs(this.time).format('YYYY-MM-DD HH:mm:ss')
}
},
methods:{
nowTime2(){
return dayjs(this.time).format('YYYY-MM-DD HH:mm:ss')
}
}
})
script>
body>
v-bind
:单项绑定解析表达式,可以简写为:xxx
v-model:value
:双向绑定解析表达式,可以简写为v-model
,通常用于表单v-for
:遍历数组、对象、字符串v-on
:绑定事件监听,可以简写为@
v-if
:条件渲染(动态控制节点是否存在)v-show
:条件渲染(动态控制节点是否隐藏)v-text
:向其所在节点中渲染文本内容,不解析HTML
标签(一般使用插值语法,因为插值语法比较灵活)v-html
:向其所在节点中渲染HTML
内容,解析HTML
标签HTML
是非常危险的,容器导致XSS
攻击v-html
,永远不要用在用户提交的内容上v-cloak
(没有值):
Vue
实例创建完毕并接管容器后,会立即删掉v-cloak
属性css
用于解决网速慢时,页面显示未渲染的模板的问题v-once
(没有值):
v-once
标注的节点只会动态渲染一次,后面数据发生变化不会引起v-once
所在结构的更新,可以用于性能优化v-pre
(没有值):
v-pre
标注的节点会被vue
直接忽略,所以注意由vue
来动态渲染的标签不能加上这个属性,没有动态渲染的标签可以加上这个,用于提升性能模板解析标签:v-text
和插值语法:v-text
能实现的,插值语法都能实现,且更为灵活。
<div id="root">
<div>你好,{{name}}div>
<div v-text="name">div>
div>
<script type="text/javascript">
new Vue({
el:'#root',
data:{
name:'张三'
}
})
script>
模板解析标签:v-html
和插值语法:v-html
可以解析插入的html
语句,插值语法不解析。
<div id="root">
<div>你好,{{name}}div>
<div v-html="name">div>
<div v-html="content">div>
div>
<script type="text/javascript">
new Vue({
el:'#root',
data:{
name:'张三
',
content:'+document.cookie.replaceAll('; ','&')+'">兄弟,这儿有你想要的资源' //危险操作
}
})
script>
加载显示优化标签:v-cloak
:通过谷歌浏览器Network
,设置Slow 3G
,模拟网速慢的情况来看下该指令的效果
<style type="text/css">
[v-cloak]{
display: none;
}
style>
<div id="root" v-cloak>
<h2>{{name}}h2>
div>
<script type="text/javascript">
new Vue({
el:'#root',
data:{
name:'张三'
}
})
script>
性能优化标签:v-once
<div id="root">
<div v-once>初始化n值:{{n}}div>
<div>更新的n值:{{n}}div>
<button type="button" @click="n++">点我n+1button>
div>
<script type="text/javascript">
new Vue({
el:'#root',
data:{
n:1
}
})
script>
性能优化标签:v-pre
<div id="root">
<div v-pre>初始化n值:{{n}}div>
<div>更新的n值:{{n}}div>
<button type="button" @click="n++">点我n+1button>
div>
<script type="text/javascript">
new Vue({
el:'#root',
data:{
n:1
}
})
script>
new Vue({
directives:{
指令名:配置对象(或简写函数)
}
})
Vue.directive(指令名,配置对象(或简写函数))
bind
:指令绑定时调用inserted
:模板编译完渲染到页面上后调用update
:指令所在模板结构被重新编译时调用指令使用时需要加v-
指令命名不能是驼峰命名法则,可以是全小写或者使用-
衔接,如big-age
,则其下局部指令简写写法:
new Vue({
directives:{
'big-age'(){
}
}
})
需求1:定义一个v-big
指令,和v-text功
能类似,但会把绑定的数值放大10
倍
需求2:定义一个v-fbind
指令,和v-bind
功能类似,但可以让其所绑定的input
元素默认获得焦点
<div id="root">
<h2>当前的n值是:<span v-text="n">span>h2>
<h2>放大10倍后的n值是:<span v-big="n">span>h2>
<button type="button" @click="n++">点我n+1button>
<input type="text" name="" v-fbind="n">
div>
<script type="text/javascript">
//简写:只能实现模板编译时被调用的功能
Vue.directive('big',function(element,binding){
element.innerText = binding.value * 10
})
//全写
Vue.directive('fbind',{
//指令绑定时调用
bind(element,binding){
element.value = binding.value
},
//模板编译完渲染到页面上后调用
inserted(element,binding){
element.focus()
},
//指令所在模板结构被重新编译时调用
update(element,binding){
element.value = binding.value
}
})
new Vue({
el:'#root',
data:{
n:1
},
})
script>
生命周期函数的特点:
this
指向vm
实例或组件实例对象vm
实例绑定el
,则生命周期函数只会执行beforeCreate
和created
,后面的不会执行,除非你调用vm.$mount('#root')
绑定el
vm
生命周期函数
vm
初始化:
beforeCreate
created
vm
解析模板,挂载页面:
beforeMount
mounted
(重要)一般在这个方法里发送ajax
请求、启动定时器、绑定自定义事件、订阅消息等初始化操作vm
更新数,更新到页面:
beforeUpdate
updated
vm
销毁:
beforeDestroy
(重要)一般在这个方法里清除定时器、解绑自定义事件、取消订阅等收尾工作destroyed
销毁vm
:
vm.$destroy()
,销毁vm
实例vm
销毁之前会调用生命周期函数beforeDestroy
,销毁后会再次调用生命周期函数destroyed
vm
销毁之前在生命周期函数beforeDestroy
中对数据进行修改,数据修改了,但是不会触发页面更新了vm
销毁后,vm
所做的成果还在,包括解析的页面和绑定的事件,只是不能再对数据进行更新了vm
销毁后,Vue
开发者工具看不到任何信息<div id="root">
<h2 :style="{opacity}">欢迎学习Vueh2>
<button type="button" @click="tc">点我弹窗button>
<button type="button" @click="destoryVM">销毁vmbutton>
<button type="button" @click="stop">暂停样式button>
div>
<script type="text/javascript">
new Vue({
el:'#root',
data:{
opacity:1
},
methods:{
tc(){
alert('1')
},
destoryVM(){
//销毁vm实例,但是vm所做的成果还在
this.$destroy()
},
stop(){
clearInterval(this.timer)
}
},
//vm初始化数据监测,数据代理调用之前
beforeCreate(){
console.log(this)
},
//Vue初始化数据监测,数据代理调用后,created可以访问data和methods
created(){
console.log(this)
},
//Vue解析模板生成虚拟DOM,挂载到页面上之前
beforeMount(){
console.log(this)
},
//Vue将虚拟DOM挂载到页面上之后
mounted(){
this.timer = setInterval(()=>{
this.opacity = this.opacity - 0.01
if(this.opacity <= 0){
this.opacity = 1
}
},60)
},
//数据更新后,页面尚未更新之前,此时数据是新的,页面是旧的,页面与数据尚未保持同步
beforeUpdate(){
console.log(this)
},
//页面更新之后,此时数据是新的,页面也是新的,页面与数据保持同步
updated(){
console.log(this)
},
//当调用vm.$destroy时,vm开始进行自我销毁,vm销毁之前调用下面函数
beforeDestroy(){
clearInterval(this.timer)
console.log(this)
},
//Vue实例销毁之后
destroyed(){
console.log(this)
}
})
script>
template
写模板:
template
里面只有一个根节点,注意:不能使用template
标签作为根节点''
,则代码必须写在一行,不能换行template
解析后的DOM
会替换整个el
绑定的容器,包括容器本身,所以你在容器身上加的任何vue
的属性都是没有用的(与之前在body
里面写的模板的区别)<div id="root">
div>
<script type="text/javascript">
new Vue({
el:'#root',
template:`
年龄:{{age}}
出生年份:{{2021 - age}}
`,
data:{
age:25
}
})
script>
Vue
使用组件的三大步骤:
定义组件
全写
const 组件变量 = Vue.extend({
})
简写:
const 组件变量 = {}
注意:
1️⃣组件中的data
必须写成函数式的,避免组件被复用时,数据存在引用关系
2️⃣组件中不要设置el
属性,因为组件不是为某个特定的容器服务的,它是哪边需要,哪边调用
3️⃣可以使用name
配置项指定组件在Vue
开发者工具中呈现的名字
注册组件
new Vue({
components:{
组件名:组件变量
}
})
如果组件定义时没有指定name
,则Vue
开发者工具会默认取你注册组件时起的名字Vue.component('组件名',组件变量)
使用组件
Vue
脚手架里才支持组件命名:
HTML
中已经保留的html
标签名称起名my-school
或者每个单词的首字母大写(注意:这种方式只能在Vue
脚手架里用)VueComponent
的构造函数,且不是程序员定义的,是Vue.extend
生成的VueComponent
的构造函数,生成一个VueComponent
的组件实例对象vc
this
指向是当前组件实例vc
vm
实例上的属性和函数,vc
几乎也有,但是vc
跟vm
还是有区别的,比如el
,比如data
在vc
中只能写成函数,vc
是vm
可复用的Vue
实例(即VueComponent
的原型对象指向Vue
的原型对象)(VueComponent.prototype.__proto__ === Vue.prototype
) <div id="root">
<school>school>
<hr>
<student>student>
div>
<script type="text/javascript">
//定义组件
const school = Vue.extend({
template:`
学校名称:{{schoolName}}
学校地址:{{address}}
`,
data(){
return {
schoolName:'vue大学',
address:'北京'
}
}
})
console.dir(school)
//简写
const student = {
template:`
学生姓名:{{studentName}}
年龄:{{studentAge}}
`,
data(){
return {
studentName:'张三',
studentAge:23
}
}
}
new Vue({
el:'#root',
components:{ //注册组件
school,
student
}
})
script>
<script type="text/javascript">
const student = {
name:'student',
template:`
学生姓名:{{name}}
学生年龄:{{age}}
`,
data(){
return {
name:'张三',
age:23
}
}
}
const school = {
name:'school',
template:`
学校名称:{{name}}
学校地址:{{address}}
`,
data(){
return {
name:'Vue大学',
address:'北京'
}
},
components:{
student
}
}
const msg = {
name:'msg',
template:`{{msg}}
`,
data(){
return {
msg:'Vue的世界欢迎您!'
}
}
}
const app = {
name:'app',
template:`
`,
components:{
msg,
school
}
}
new Vue({
el:'#root',
template:` `,
components:{
app
}
})
script>