vue基础
什么是vue?
Vue(轻量级框架)是一套用于构建用户界面的渐进式框架。与其它大型框架不同的是,Vue 被设计为可以自底向上逐层应用。Vue 的核心库只关注视图层,不仅易于上手,还便于与第三方库或既有项目整合。另一方面,当与现代化的工具链以及各种支持类库结合使用时,Vue 也完全能够为复杂的单页应用提供驱动。
Vue的特点
-
1.采用组件化模式,提高代码复用率,且让代码更好维护。
-
2.声明式编码(还有命令式编码),让编码人员无需直接操作DOM,提高开发效率。
-
3.使用虚拟的DOM+优秀的Diff算法,尽量复用DOM节点
-
4.安装Vue Devtools插件
在官网上点击进入学习 =>Vue Devtools=>下载将下载好的文件拖入到游览器的拓展程序里面
初识Vue
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<!--准备好一个容器-->
<div id="root">
<!-- 插值语法 双括号里面必须写js表达式 注意区分js表达式(一个值) 和 js代码-->
<h1>Hello,{{name}}!</h1>
</div>
<script type="text/javascript">
//设置为 false 以阻止 vue 在启动时生成生产提示
Vue.config.productionTip = false;
//创建Vue实例{只能操作一个对象(配置对象)}
let vm = new Vue({
//element元素
//用于指定当前Vue实例为那个容器服务,值通常为css选择器字符串
//document.getElementById('root')
el: '#root',
data: {//data中用于存储数据,数据供el所指定的容器去使用,值我们暂时先写成一个对象
name: '恋椿'
},
})
</script>
</body>
</html>
总结:
1.想让Vue工作,就必须创建一个Vue实例,且要传入一个配置对象; 2.root容器里的代码依然符合HTML规范,只不过混入了一些特殊的Vue语法; 3.root容器里的代码被称为【Vue模版】; 4.vue与容器的关系为1对1 5.真实开发中只有一个Vue实例,并且配合着组件一起使用; 6.{{xxx}}中的xxx要写js表达式,且xxx可以自动读取到data中的所有属性 7.一旦data中的数据发生改变,那么页面中用到该数据的地方也会自动更新; 注意区分js表达式 和 js代码- 1.表达式:一个表达式会产生一个值,可以放在任何一个需要值的地方: (1). a (2). a+b (3). demo(1) (4). x === y? 'a' : 'b' 2.js代码(语句) (1). if(){} (2). for(){}
模板语法
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<!--准备好一个容器-->
<div id="root">
<!-- 指令语法-->
<a v-bind:href="url">点我去学习</a>
<!-- 可以简写成-->
<a :href="url">点我去学习</a>
</div>
<script type="text/javascript">
//创建Vue实例{只能操作一个对象}
let vm = new Vue({
//element元素
//用于指定当前Vue实例为那个容器服务,值通常为css选择器字符串
el: '#root',
data: {//data中用于存储数据,数据供el所指定的容器去使用
name: '恋椿',
url:'http://www.atguigu.com',
},
})
</script>
</body>
</html>
总结:
Vue模版语法有两大类 1.插值语法: 功能:用于解析标签体内容 写在标签体内 写法:{{xxx}},xxx是js表达式,且可以直接读取到data中的所有属性值。 2.指令语法: 写在标签内部 功能:用于解析标签(包括:标签属性、标签体内容、绑定事件...) 举例:v-bind:href="xxx" 或者可以简写为 :href="xxx",xxx同样要写js表达式, 且可以直接读取到data中的所有属性。 标签体内用插值语法,标签属性内用指令语法
数据绑定:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<!--准备好一个容器-->
<div id="root">
单项数据绑定:<input type="text" :value="name"></br>
<!-- v-model只能应用在表单类元素上(输入类元素、有value值)-->
双向数据绑定:<input type="text" v-model="name">
</div>
<script type="text/javascript">
//创建Vue实例{只能操作一个对象}
let vm = new Vue({
el: '#root',
data: {//data中用于存储数据,数据供el所指定的容器去使用
name: '恋椿',
},
})
</script>
</body>
</html>
总结:
vue中有两种数据绑定 1.单项绑定(v-bind):数据只能从data中流向页面 2.双向绑定(v-model:value):可以简写为v-model,因为v-model默认收集的就是value值
el与data的两种写法:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<!--准备好一个容器-->
<div id="root">
<h1>{{name}}</h1>
</div>
<script type="text/javascript">
let vm = new Vue({
//el的第一种写法
// el: '#root',
//data的第一种写法:对象式
// data: {//data中用于存储数据,数据供el所指定的容器去使用
// name: '恋椿',
// },
// data的第二种写法函数式 用组件的时候必须使用函数式的写法,this代表的是vue实例
data: function () {
console.log("ddd", this)
return {
name: '恋椿'
}
}
})
//el的第二种写法 mount 挂载、放
vm.$mount("#root")
</script>
</body>
</html>
总结:
data与el的2种写法 1.el有两种写法 (1).new Vue时候配置el (2).先创建Vue实例,随后在通过vm.$mount('#root')指定el的值 2.data的有两种写法 (1).对象式 (2).函数式 用组件的时候必须使用函数式的写法 3.一个重要的原则: 由Vue管理的函数,一定不要写箭头函数,一旦写了箭头函数,this就不是Vue实例了(否则this就是window对象)
MVVM模型:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<!--准备好一个容器-->
<div id="root">
<h1>学校名称:{{name}}</h1>
<h1>学校地址:{{address}}</h1>
</div>
<script type="text/javascript">
let vm = new Vue({
el: '#root',
data: {
name: '恋椿',
address: '北大',
},
})
</script>
</body>
</html>
总结:
vue中有两种数据绑定 MVVM模型 1. M:模型(model):data中的数据 2. V:视图(view):模版代码 3. VM 视图模版(ViewModel):Vue实例 观察发现 1.data中的所有属性:最后都出现在了vm身上 2.vm身上所有的属性 及 Vue原型上的所有属性,在Vue模版中都可以直接使用
数据代理:
Object.defineProperty方法
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>回顾Object.defineProperty方法</title>
</head>
<body>
<script type="text/javascript">
let number = 18;
let person = {
name: '张三',
sex: '男',
}
//追加属性 给谁追加 属性名
Object.defineProperty(person, 'age', {
// //age不参与遍历 不能枚举
// value: number,
//
// //控制属性是否可以枚举、遍历 默认false
// enumerable: true,
//
// //控制属性是否可以被修改 默认false
// writable: true,
//
// // 控制属性能否被删除 默认false
// configurable: true,
//当有人读取person的age属性时,get函数(getter)就会被调用且返回值就是age的值
get() {
console.log("有人读取了age")
return number;
},
set(value) {
console.log("有人修改了age:" + value);
number = value;
}
})
//可以把传入对象的所有属性的属性名提取出来变成一个数组
console.log(Object.keys(person))
for (let key in person) {
console.log(person[key])
}
console.log(person)
</script>
</body>
</html>
什么是数据代理?
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>什么是数据代理</title>
</head>
<body>
<!--数据代理:通过一个对象代理另一个对象中的属性的操作-->
<script type="text/javascript">
let obj = {x: 100}
let obj2 = {y: 100}
Object.defineProperty(obj2, 'x', {
get() {
return obj.x
},
set(value) {
obj.x = value
}
})
</script>
</body>
</html>
Vue中的数据代理
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Vue中的数据代理</title>
<script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<div id="root">
<h2>学校名称:{{name}}</h2>
<h2>学校地址:{{address}}</h2>
<h2></h2>
</div>
<script type="text/javascript">
Vue.config.productionTip = false;
let vm = new Vue({
el: "#root",
//_data==data ——>将data内的数据挂到vm身上
//_data中的数据是数据劫持不是数据代理
data: {
name: '叨叨学院',
address: '叨叨市叨叨路',
}
})
</script>
</body>
</html>
总结:
1.Vue中的数据代理:
通过vm来代理data对象中属性的操作(读/写)
2.Vue中的数据代理的好处:
更加方便的操作data中的数据
3.基本原理:
通过Object.defineProperty()把data对象中的所有属性添加到vm上。
为每一个添加到vm上的属性,都制定一个getter/setter。
在getter/setter内部去操作(读/写)data中对应的属性
事件的处理:
基本使用
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>事件的基本使用</title>
<script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<div id="root">
<h2>欢迎来到{{name}}学院学习</h2>
<button v-on:click="showInfo1">点我提示信息1</button>
<!-- 简写-->
<button @click="showInfo2(666,$event)">点我提示信息2</button>
</div>
</body>
<script type="text/javascript">
Vue.config.productionTip=false;
const vm = new Vue({
el:'#root',
data:{
name:'叨叨叨'
},
methods:{
showInfo1(event){//触发事件的元素
// console.log(event.target)
alert('叨叨同学你好!')
},
showInfo2(number,event){//触发事件的元素
console.log(number)
alert('叨叨同学你好!!')
}
}
})
</script>
</html>
总结:
所有被Vue所管理的方法都写成普通方法
事件的基本使用:
1.使用v-on:xxx 或 @xxx 绑定事件, 其中xxx是事件名;
2.事件的回调需要配置在methods对象中,最终会在vm身上;
3.methods配置的函数,不要用箭头函数!否则this就不是vm了;
4.methods配置的函数,,都是被Vue所管理的函数,this的指向是vm 或 组件实例对象;
5.@click='demo' 和 @click='demo($event)' 效果一致,但后者可以传参;
事件的修饰符
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>事件的基本使用</title>
<script type="text/javascript" src="../js/vue.js"></script>
<style>
*{
margin-top: 30px;
}
.demo1{
height: 50px;
background-color: pink;
}
.box1{
padding: 5px;
background-color: green;
}
.box2{
padding: 5px;
background-color: orange;
}
.list{
width: 200px;
height: 200px;
background-color: peru;
overflow: auto;
}
li{
height: 100px;
}
</style>
</head>
<body>
<div id="root">
<h2>欢迎来到{{name}}学院学习</h2>
<!-- 1.prevent:阻止默认事件(常用);-->
<a href="http://www.baidu.com" @click.prevent="showInfo">点我提示信息1</a>
<!-- 2.stop:阻止事件冒泡(常用);-->
<!-- 先调用子代的事件在调用自身的(从上到下捕捉然后触底反弹开始冒泡) -->
<div class="demo1" @click="showInfo2">
<button @click.stop="showInfo">点我提示信息2</button>
</div>
<!-- 3.once:事件只触发一次(常用);-->
<div class="demo1">
<button @click.once="showInfo">点我提示信息3</button>
</div>
<!-- 4.capture:使用事件的捕获方式;-->
<div class="box1" @click.capture="showMsg(1)">
div1
<div class="box2" @click="showMsg(2)">
div2
</div>
</div>
<!-- 5.self:只有event.target是当前操作的元素时才触发事件;-->
<div class="demo1" @click.self="showInfo2">
<button @click="showInfo">点我提示信息2</button>
</div>
<!-- 6.passive:事件的默认行为立即执行,无需等待事件回调执行完毕;-->
<!-- @scroll是给滚动条加的滚动事件 @wheel是给鼠标的滚轮添加的滚动事件-->
<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.productionTip = false;
new Vue({
el: '#root',
data: {
name: '叨叨叨'
},
methods: {
showInfo(e) {
// e.preventDefault() //阻止默认行为
// e.stopPropagation() //阻止冒泡事件
alert('同学你好!')
// console.log(e.target)
},
showInfo2(e) {
console.log(e.target)
alert('ddd!')
},
showMsg(msg) {
console.log(msg)
},
demo() {
for (let i=0;i<100000;i++) {
console.log("#")
}
console.log("累不")
}
}
})
</script>
</html>
总结:
Vue中的事件修饰符:
1.prevent:阻止默认事件(常用);
2.stop:阻止事件冒泡(常用);
3.once:事件只触发一次(常用);
4.capture:使用事件的捕获方式;
5.self:只有event.target是当前操作的元素时才触发事件;
6.passive:事件的默认行为立即执行,无需等待事件回调执行完毕;
注意修饰符可以连续写
键盘事件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>事件的基本使用</title>
<script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<div id="root">
<h2>欢迎来到{{name}}学院学习</h2>
<!-- @keydown按下按键不用抬起来就触发 @keyup按下按键抬起来才触发-->
<input type="text" placeholder="按下回车提示输入" @keyup.ctrl.a="showInfo">
</div>
</body>
<script type="text/javascript">
Vue.config.productionTip = false;
new Vue({
el: '#root',
data: {
name: '叨叨叨'
},
methods: {
showInfo(e) {
// if (e.keyCode !== 13) return
console.log(e.target.value)
// console.log(e.key,e.keyCode)
}
},
})
</script>
</html>
总结:
1.Vue中常用的案件别名:
回车=>enter
删除=>delete(捕获“删除”和“退格“ 键)
退出=>esc
空格=>space
换行=>tab 特殊keyup不适合用tab,不许用keydown
上=>up
下=>down
左=>left
右=>right
2.Vue未提供别名的按键,可以使用按键的原始key去绑定,但注意要转为kebab(短横命名)
***例如CapsLock按键的key值为CapsLock,用的时候得写成caps-lock
3.系统修饰键(用法特殊):ctrl、alt、shift、meta
(1).配合keyup使用:按下修饰键的同时,再按下其他键,随后释放其他键,事件才被触发
指定和修饰键组合的按键 @keyup.ctrl.y="showInfo"
(2).配合keydown使用:正常触发事件。
4.也可以使用keyCode去指定具体的按键(不推荐)
5.Vue.config.keyCodes.自定义键名=建码,可以去定义按键别名
计算属性
三种方式:
插值语法实现
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>1.姓名案例_插值语法.html</title>
<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>
姓名:<span>{{firstName}}-{{lastName}}</span>
</div>
</body>
<script type="text/javascript">
Vue.config.productionTip = false;
new Vue({
el: '#root',
data: {
firstName: '张',
lastName: '三'
},
methods: {
showInfo() {
}
}
})
</script>
</html>
methods实现
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>1.姓名案例_插值语法.html</title>
<script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<!--
只要Vue中的数据发生变化,Vue将重新解析模版,重新调用函数
-->
<div id="root">
姓:<input type="text" v-model="firstName"><br/>
名:<input type="text" v-model="lastName"><br/>
姓名:<span>{{fullName()}}</span>
</div>
</body>
<script type="text/javascript">
Vue.config.productionTip = false;
new Vue({
el: '#root',
data: {
firstName: '张',
lastName: '三',
age:18
},
methods: {
fullName() {
console.log(123)
return this.firstName+'-'+this.lastName
}
}
})
</script>
</html>
计算属性实现
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>姓名案例_计算属性实现</title>
<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>{{fullName}}</span><br/>
<!-- 有缓存,初次读取时会调用,所以来的数据发生变化时重新调用-->
姓名:<span>{{fullName}}</span><br/>
姓名:<span>{{fullName}}</span><br/>
姓名:<span>{{fullName}}</span><br/>
</div>
</body>
<script type="text/javascript">
Vue.config.productionTip = false;
let vm= new Vue({
el: '#root',
data: {
firstName: '张',
lastName: '三'
},
computed:{
fullName:{
//get有什么作用?当有人读取fullName时,get就会被调用,且返回值就作为fullName的值
get(){
return this.firstName + '-' + this.lastName
},
set(value){
console.log('set',value)
const arr=value.split('-')
this.firstName=arr[0]
this.lastName=arr[1]
}
}
}
})
</script>
</html>
总结:
计算属性:
1.定义:要用的属性不存在,要通过已有的属性计算得来
2.原理:底层借助了Object.defineproperty方法提供的getter和setter。
3.get函数什么时候执行
(1).初次读取时会执行一次
(2).当依赖的数据放生变化时会被再次调用
4.优势: 与methods实现相比,内部有缓存机制(复用),效率更高,调试更方便。
5.备注:
(1).计算的属性最终会出现在vm上,直接去读取即可
(2).如果计算属性要被修改,必须写set函数去响应修改,且set中要引起计算时依赖的数据发生变化
计算属性简写
当确定只读取不修改时可以这样写,计算属性中不能开启异步任务去维护数据
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>姓名案例_计算属性实现</title>
<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>{{fullName}}</span><br/>
</div>
</body>
<script type="text/javascript">
Vue.config.productionTip = false;
let vm = new Vue({
el: '#root',
data: {
firstName: '张',
lastName: '三'
},
computed: {
fullName: function () {
return this.firstName + '-' + this.lastName
},
// fullName: function () {
// setTimeout(()=>{
// return this.firstName + '-' + this.lastName
// },1000)
//
// }
}
})
</script>
</html>
监视属性
天气案例:当点击按钮时切换天气
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>监视属性</title>
<script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<div id="root">
<h2>今天天气很{{info}}</h2>
<button @click="changeWeather">切换天气</button>
<!-- 简化版 可以写一些简单的语句-->
<button @click="isHot=!isHot">切换天气</button>
</div>
</body>
<script type="text/javascript">
Vue.config.productionTip=false;
new Vue({
el:'#root',
data:{
isHot:true
},
computed:{
info(){
return this.isHot ? '炎热' : '凉爽'
}
},
methods:{
changeWeather(){
this.isHot=!this.isHot
}
}
})
</script>
</html>
使用监视属性完成
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>事件的基本使用</title>
<script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<div id="root">
<h2>今天天气很{{info}}</h2>
<button @click="changeWeather">切换天气</button>
</div>
</body>
<script type="text/javascript">
Vue.config.productionTip=false;
const vm= new Vue({
el:'#root',
data:{
isHot:true
},
computed:{
info(){
return this.isHot ? '炎热' : '凉爽'
}
},
methods:{
changeWeather(){
this.isHot=!this.isHot
}
},
watch:{
info:{
// immediate:true,//初始化时让handler调用一下
handler(newValue,oldValue){
console.log('isHot被修改了')
console.log('newValue:'+newValue)
console.log('oldValue:'+oldValue)
}
}
}
})
// vm.$watch('isHot',{
// // immediate:true,//初始化时让handler调用一下
// handler(newValue,oldValue){
// console.log('isHot被修改了')
// console.log(newValue)
// console.log(oldValue)
// }
// })
</script>
</html>
总结:
监视属性watch:
1.当监视属性变化时,回调函数自动调用,进行相关操作
2.监视的属性必须存在,才能进行监视
3.监视的两种写法:
(1).new Vue时传入watch配置
(2).通过vm.$watch监视
深度监视
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>深度监视</title>
<script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<div id="root">
<h2>今天天气很{{info}}</h2>
<button @click="changeWeather">切换天气</button>
<hr/>
<h3>a的值为:{{numbers.a}}</h3>
<button @click="numbers.a++">点我a++</button>
<hr/>
<h3>b的值为:{{numbers.b}}</h3>
<button @click="numbers.b++">点我b++</button>
</div>
</body>
<script type="text/javascript">
Vue.config.productionTip = false;
const vm = new Vue({
el: '#root',
data: {
isHot: true,
numbers: {
a: 1,
b: 2
}
},
computed: {
info() {
return this.isHot ? '炎热' : '凉爽'
}
},
methods: {
changeWeather() {
this.isHot=!this.isHot
}
},
watch: {
isHot: {
handler(newValue, oldValue) {
console.log('isHot被修改了')
console.log('newValue:'+newValue)
console.log('oldValue:'+oldValue)
}
},
//监视多级结构中某个属性的变化
// 'numbers.a':{
// handler(newValue, oldValue) {
// console.log('a的值被改变')
// }
// }
//监视多级结构中所有属性的变化
numbers: {
deep: true,//开启深度监视
handler(newValue, oldValue) {
console.log('numbers改变了')
}
}
}
})
</script>
</html>
总结:
深度监视:
(1).Vue中的watch默认不监测对象内部值的改变(一层)
(2).配置deep:true可以监测对象内部值改变(多层)
备注:
(1).Vue自身可以监测对象内部值的改变,但Vue提供的watch默认不可以!
(2).使用watch时根据数据的具体结构,决定是否采用深度监视
深度监视简写
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>深度监视</title>
<script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<div id="root">
<h2>今天天气很{{info}}</h2>
<button @click="changeWeather">切换天气</button>
</div>
</body>
<script type="text/javascript">
Vue.config.productionTip = false;
const vm = new Vue({
el: '#root',
data: {
isHot: true,
},
computed: {
info() {
return this.isHot ? '炎热' : '凉爽'
}
},
methods: {
changeWeather() {
this.isHot = !this.isHot
}
},
watch: {
//正常写法
// isHot: {
// handler(newValue, oldValue) {
// console.log('isHot被修改了')
// console.log(newValue)
// console.log(oldValue)
// }
// }
// 简写 前提 immediate deep 不需要改变时
// isHot(newValue,oldValue){
// console.log('isHot被修改了',newValue,oldValue)
// }
}
})
//完整写法
// vm.$watch('isHot',{
// immediate:true,
// depp:true,
// handler(newValue,oldValue){
// console.log('isHot被修改了',newValue,oldValue)
//
// }
// })
// 简写
vm.$watch('isHot',function (newValue,oldValue){
console.log('isHot被修改了',newValue,oldValue)
})
</script>
</html>
总结:
深度监视:
(1).Vue中的watch默认不监测对象内部值的改变(一层)
(2).配置deep:true可以监测对象内部值改变(多层)
备注:
(1).Vue自身可以监测对象内部值的改变,但Vue提供的watch默认不可以!
(2).使用watch时根据数据的具体结构,决定是否采用深度监视
watch实现
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>姓名案例_计算属性实现</title>
<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>{{fullName}}</span><br/>
</div>
</body>
<script type="text/javascript">
Vue.config.productionTip = false;
let vm = new Vue({
el: '#root',
data: {
firstName: '张',
lastName: '三',
fullName: '张-三'
},
watch: {
// firstName(newValue) {
// setTimeout(()=>{
// this.fullName = newValue + '-' + this.lastName
// },1000)
// },
firstName(newValue) {
this.fullName = newValue + '-' + this.lastName
},
lastName(newValue) {
this.fullName = this.firstName + '-' + newValue
}
}
})
</script>
</html>
总结:
当确定只读取不修改时可以这样写
watch中可以开启异步任务去维护数据
定时函数不属于Vue所管理的
computed 和 watch之间的区别:
1.computed能完成的功能,watch都能完成
2.watch能完成的功能computed不一定能完成,例如:watch可以进行异步操作。
两个重要的小原则:
1.所有被Vue所管理的函数,做好写成普通函数,这样this的指向才是 vm 或 组件实例对象。
2.所有不得Vue所管理的函数(定时器的回调函数、ajax的回调函数等),最好写成箭头函数,这样this的指向才是 vm 或 组件实例对象。
绑定样式
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>绑定样式</title>
<style>
.basic {
border: 1px solid black;
}
.happy {
border: 1px solid pink;
background-color: red;
}
.sad {
border: 2px double green;
background-color: #807f80;
}
.normal {
border: 2px solid black;
background-color: #7fc6eb;
}
.lianChun1 {
background-color: lawngreen;
}
.lianChun2 {
background-color: red;
font-weight: bold;
}
.lianChun3 {
border-radius: 5px;
}
</style>
<script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<!--准备好一个容器-->
<div id="root">
<!-- 绑定class样式 -字符串写法 适用于 : 样式的类名不确定,需要动态指定 -->
<div class="basic" :class="mood" @click="changeMood">{{name}}</div>
<br/>
<!-- 绑定class样式 -数组写法 适用于 : 要绑定的样式个数不确定,名字也不确定 -->
<div class="basic" :class="arr" >{{name}}</div>
<br/>
<!-- 绑定class样式 -对象写法 适用于 : 要绑定的样式确定,名字确定,但要动态的决定用不用 -->
<div class="basic" :class="classObj">{{name}}</div>
<br>
<div class="basic" :style="{fontSize: fsize + 'px'}">{{name}}</div>
<div class="basic" :style="styleObj">{{name}}</div>
</div>
</body>
<script>
Vue.config.productionTip=false;
const vm= new Vue({
el: '#root',
data: {
name: '恋椿',
mood: 'normal',
arr:['lianChun1','lianChun2','lianChun3'],
classObj:{
lianChun1:false,
lianChun2:false,
},
fsize:'40',
},
methods: {
changeMood() {
// document.getElementById("root").className='basic happy';
//this.mood = 'happy'
const arr=['happy','sad','normal']
// 随机生成随机数
const index=Math.floor(Math.random()*3)
this.mood=arr[index]
// 网页测试 删除样式 vm.arr.shift() vm.arr.push('lianChun1')
}
}
})
</script>
</html>
条件渲染
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>条件渲染</title>
<script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
<!--准备好一个容器-->
<div id="root">
<p v-if="num==1">百度</p>
<p v-else-if="num==2">腾讯</p>
<p v-else="num==3">阿里</p>
<p v-if="num==4">痘印</p>
<p v-show="num==1">天猫</p>
<p v-show="num==2">淘宝</p>
</div>
</body>
<script>
Vue.config.productionTip = false;
const vm = new Vue({
el: "#root",
data() {
return {
num: 2
}
}
})
</script>
</html>
总结:
v-if 和 v-show的区别
如果需要频繁的切换使用show较好
当条件不成立,v-if内的所有子节点不会解析(项目中使用)
循环及列表过滤
语法:
v-for="(item, index) in xxx" :key=“yyy”
使用:
- 可遍历:数组、对象、字符串(用的很少)、指定次数(用的很少)
- v-for 指令需要使用 item in items 形式的特殊语法,其中 items 是源数据数组,而 item 则是被迭代的数组元素的别名(形参)。
- v-for 还支持一个可选的第二个参数,即当前项的索引。
- 可以用 of 替代 in 作为分隔符,因为它更接近 JavaScript 迭代器的语法:
- 数组: (item, index)
- 对象: (value, key)
- 字符串:(char, index)
- 数字:(number, index)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Vue初体验</title>
<!-- 1.引入Vue -->
<script src="../js/vue.js"></script>
</head>
<body>
<!-- 2.准备一个容器 -->
<div id="root">
<h1>数组遍历</h1>
<input type="text" placeholder="请输入要查询的姓名" v-model="keyWord">
<button @click="sortType = 2 ">年龄升序</button>
<button @click="sortType = 1 ">年龄降序</button>
<button @click="sortType = 0 ">复原</button>
<table cellpadding="0" cellspacing="0" border="1">
<thead>
<th width="100px">ID</th>
<th width="100px">姓名</th>
<th width="100px">年龄</th>
</thead>
<tr v-for="(user,index) in userListFil" :key="user.id" align="center">
<td>{{user.id}}</td>
<td>{{user.name}}</td>
<td>{{user.age}}</td>
</tr>
</table>
</div>
<script>
//3.创建Vue实例
const vm = new Vue({
el:'#root',
data:{
userList:[
{id:1,name:'张飞',age:18},
{id:2,name:'刘备',age:19},
{id:3,name:'关羽',age:20},
{id:4,name:'曹操',age:18},
{id:5,name:'关平',age:19},
{id:6,name:'曹植',age:20},
],
keyWord:'',
sortType:0,
},
computed:{
// 只过滤
// userListFil(){
// return this.userList.filter((user)=>{ //将userList下的所有对象都交给user
// return user.name.indexOf(this.keyWord) !== -1 //查找是否包含keyWord
// })
// }
userListFil(){
const arr = this.userList.filter(user=>{
return user.name.indexOf(this.keyWord) !== -1;
});
//判断是否排序
if (this.sortType !== 0){
//sort函数要比较两个值,然后返回一个用于说明这两个值的相对顺序的数字。
arr.sort((p1,p2)=>{ //将原位置(p1) 和后一个(p2) 进行比较
if(p1.age - p2.age < 0){ //如果p1的年龄大于p2
console.log(p1.age + "小于" + p2.age + "调换位置")
}else if(p1.age - p2.age > 0){
console.log(p1.age + "大于" + p2.age + "位置不变")
}else {
console.log(p1.age + "等于" + p2.age + "位置不变")
}
return this.sortType === 1 ? p2.age - p1.age : p1.age - p2.age;
});
}
return arr;
}
}
});
</script>
</body>
</html>
key的原理:
- 有相同父元素的子元素必须有独特的 key。重复的 key 会造成渲染错误
收集表单数据:
- 若:type=text、password、number,则v-model默认收集的是value值,用户输入的就是value值。
- 若:type=radio,则v-model默认收集的是value值,因为此类型无法输入内容,则无法通过输入得到value值,所以要给标签手动添加value值。
- 若:type=checkbox
没有配置input的value属性,那么默认读取的的就是checked是否被勾选(勾选 or 未勾选,是布尔值)
配置input的value属性:
v-model的初始值是非数组,那么收集的就是checked(勾选 or 未勾选,是布尔值)
v-model的初始值是数组,那么收集的的就是value组成的数组
- 备注:v-model的三个修饰符:
lazy:失去焦点再收集数据
number:输入字符串转为有效的数字
trim:输入首尾空格过滤
Vue指令
内置指令 | 解释 |
v-text | 更新元素的 textContent |
v-html | 更新元素的 innerHTML |
v-if | 如果为true, 当前标签才会输出到页面 |
v-else | 如果为false, 当前标签才会输出到页面 |
v-show | 通过控制display样式来控制显示/隐藏 |
v-for | 遍历数组/对象 |
v-on | 绑定事件监听, 一般简写为@ |
v-bind | 强制绑定解析表达式, 可以省略v-bind |
v-model | 双向数据绑定 |
v-text与v-html的区别:
v-text : 更新元素的 textContent
- 作用:向其所在的节点中渲染文本内容。
- 与插值语法的区别:v-text会替换掉节点中的内容,{{xx}}则不会。
v-html : 更新元素的 innerHTML
- 作用:向指定节点中渲染包含html结构的内容。
- 与插值语法的区别:
- v-html会替换掉节点中所有的内容,{{xx}}则不会。
- v-html可以识别html结构。
注意:v-html有安全性问题!!!!
- 在网站上动态渲染任意HTML是非常危险的,容易导致XSS攻击。
- 一定要在可信的内容上使用v-html,永不要用在用户提交的内容上!
v-once与v-pre
v-once
- v-once所在节点在初次动态渲染后,就视为静态内容了。
- 以后数据的改变不会引起v-once所在结构的更新,可以用于优化性能。
v-pre
- 跳过其所在节点的编译过程。(vue 不去解析 插值等语法)
- 可利用它跳过:没有使用指令语法、没有使用插值语法的节点,会加快编译。
ref与v-cloak
ref
- 为某个元素注册一个唯一标识, vue对象通过$refs属性访问这个元素对象。
v-cloak
- 使用它防止闪现表达式, 与css配合: [v-cloak] { display: none }
- 本质是一个特殊属性,Vue实例创建完毕并接管容器后,会删掉v-cloak属性。
- 使用css配合v-cloak可以解决网速慢时页面展示出{{xxx}}的问题。
自定义指令
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Vue初体验</title>
<!-- 1.引入Vue -->
<script src="../js/vue.js"></script>
</head>
<body>
<!-- 2.准备一个容器 -->
<div id="root">
<h1>当前n的值是:<span v-text="num"></span></h1>
<h1>放大10倍后的n的值是:<span v-big="num"></span></h1>
<button @click="num++">点击num+1</button>
<hr>
<input type="text" v-fbind:value="num">
</div>
<script>
//3.创建Vue实例
const vm = new Vue({
el:'#root',
data:{
num:10,
},
directives:{
big(el,binding){
el.innerText = binding.value * 10;
},
fbind:{
bind(el,binding){
el.value = binding.value;
},
// 指令的定义
inserted(el,binding){
el.focus();
},
update(el,binding){
el.value = binding.value;
el.focus();
}
}
},
});
</script>
</body>
</html>