官方概念:Vue 是一套用于构建用户界面的前端框架
在使用了vue 的页面中,vue 会监听数据的变化,从而自动重新渲染页面结构。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-praodxFJ-1652883437021)(C:\Users\肖锦顺\AppData\Roaming\Typora\typora-user-images\1649771840707.png)]
好处:当页面数据发生变化是,页面会自动重新渲染
注意:数据驱动视图是单向绑定数据
在填写表单时,双向数据绑定可以辅助开发者在不操作 DOM 的前提下,自动把用户填写的内容同步到数据源中。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JWDZJH9v-1652883494710)(C:%5CUsers%5C%E8%82%96%E9%94%A6%E9%A1%BA%5CAppData%5CRoaming%5CTypora%5Ctypora-user-images%5C1649771840707.png#pic_center)]
好处:开发者不再需要手动操作 DOM 元素,来获取表单元素的最新值
MVVM 是 Vue 实现数据驱动视图和双向数据绑定的核心原理。MVVM 指的是 Model、View、ViewModel。它把每个 HTML 页面都拆分成了这三部分
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9X58q5iF-1652883437023)(C:\Users\肖锦顺\AppData\Roaming\Typora\typora-user-images\1649772195609.png)]
ViewModel 作为 MVVM 的核心,是它把当前页面数据源(Model)和页面结构 (View)连接在一起。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gypxIBRb-1652883437023)(C:\Users\肖锦顺\AppData\Roaming\Typora\typora-user-images\1649772286174.png)]
当数据源发生变化是,会被 ViewModel 监听到,VM 会根据最新的数据源自动更新页面结构
当表单元素的值发生变化是,也会被 VM 监听到,VM 会把变化过后的最新的值自动同步到 Model 数据源中。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sbCvpJp4-1652883437023)(C:\Users\肖锦顺\AppData\Roaming\Typora\typora-user-images\1649772513596.png)]
指令是 vue 为开发者提供的模板语法,用于辅助开发者渲染页面的基本结构
Vue 指令的 6 大类:
内容渲染指令用来辅助开发者渲染 DOM 元素的文本内容。常用的内容渲染指令有如下 3 个
v-text
用法
<p v-text="gender">性别p>
{{}}
vue 提供的 {{}} 语法,专门用来解决 v-text 会覆盖默认文本内容的问题。这种语法 {{}} 的专业名称是插值表达式(英文:Mustache)
<p>
姓名:{{username}}
p>
v-html
v-text 指令和插值表达式只能渲染存文本内容。如果要把包含 HTML 标签的字符串渲染为页面的 HTML 元素,则需要用到 v-html 指令
<p v-html="discription"> p>
为元素绑动态绑定属性值,可以使用 v-bind 属性绑定指令
<div id="app">
<input type="text" v-bind:placeholder="tips"><br>
<input type="text" :placeholder="tips">
<hr>
<div>{{ 1 + 2}}div>
<div>{{ tips}} 翻转的结果是: {{ tips.split('').reverse().join('')}}div>
div>
<script src="./lib/vue-2.6.12.js">script>
<script>
// 创建 Vue 实例对象
const vm = new Vue({
// el 是固定的写法,表示 vm 要控制页面上的哪一个区域,接受的值是一个选择器
el:'#app',
// data 对象就是要渲染到页面上的数据
data:{
tips:'请输入用户名',
index:3,
}
})
script>
vue 提供的模板语法渲染语法中,除了支持绑定简单的数据值之外,还支持 JavaScript 表达式的运算
{{ ok ? 'yes' : 'no' }}
<div v-bind="'list'+id">
div>
vue 提供了 v-on 事件绑定指令,用来辅助程序员为 DOM 元素绑定事件监听
<div id="app">
<p>count 的值是:{{ count}}p>
<button @click='add(2)'>+1button>
<button v-on:click='sub'>-1button>
div>
<script src="./lib/vue-2.6.12.js">script>
<script>
// 创建 Vue 实例对象
const vm = new Vue({
// el 是固定的写法,表示 vm 要控制页面上的哪一个区域,接受的值是一个选择器
el:'#app',
// data 对象就是要渲染到页面上的数据
data:{
count:0,
},
// methods 的作用就是定义事件处理函数
methods:{
// add:function(){
// }
// 处理函数简写形式
add(n){
// console.log(vm === this) // this 就是 vm这个 Vue 实例对象
// 调用 count 属性
this.count +=n
},
sub(){
this.count -=1
}
}
});
注意:原生 DOM 对象有 onclick、oninput、onkeyup 等原生事件
事件绑定之后为:v-on:click v-on:input v-on:keyup
事件参数对象
在原生的 DOM 对象绑定中,可以在事件处理函数的形参处,接受事件对象 event。同理,在 v-on 指令所绑定的事件处理函数中,同样可以接收到事件对象 event
<div id="app">
<p>count的值是 {{count}}p>
<button @click="add">+1button>
div>
<script src="./lib/vue-2.6.12.js">script>
<script>
// 创建 Vue 实例对象
const vm = new Vue({
// el 是固定的写法,表示 vm 要控制页面上的哪一个区域,接受的值是一个选择器
el:'#app',
// data 对象就是要渲染到页面上的数据
data:{
count:0,
},
methods:{
add(e){ // 接受事件对象 event ,简写为 e
// 调用是不传参数,会有一个参数e
e.target.style.backgroundColor = 'red'
},
}
});
在使用 v-on 指令绑定事件时,可以使用 ()进行传参
count的值为:{{count}}
// -------------------------------------
methods:{
add(n) {
// 用 n 接受参数
this.count += n
}
}
$event 是 vue 提供的特殊变量,用来表示原生的事件参数对象 event。
$event 可以解决事件参数对象 event 被覆盖的问题
<!-- Vue 提供了内置变量,名为 $event,它就是 DOM 的原生对象 e -->
<button @click="add(1,$event)">+N</button>
// -------------------------------------
methods: {
add(n,e) {
// 使用 e 来接受传递过来的原生事件对象 $event
this.count += n
e.target.style.backgroundColor = 'red'
}
}
事件修饰符
.prevent
<a @click.prevent="xxx">链接a>
.stop
<button @click.stop="xxx">按钮button>
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZCQvkY4p-1652883437024)(C:\Users\肖锦顺\AppData\Roaming\Typora\typora-user-images\1649826528524.png)]
按键修饰符
在监听键盘事件时,我们经常需要判断详细的按键。此时,可以为键盘相关事件添加按键修饰符
<!-- 绑定一个按键修饰符 -->
<input type="text" @keyup.esc="clearInfo">
methods:{
clearInfo(e){
console.log('触发了按键修饰符')
e.target.value = ''
}
}
vue 提供了 v-model 双向绑定数据指令
<div id="app">
<p>用户的姓名是:{{ username}}</p>
<!-- 使用 v-model 双向绑定 -->
<input type="text" v-model="username">
<hr>
请选择:<select name="" id="" v-model="city">
<option value="1">北京</option>
<option value="2">上海</option>
<option value="3">武汉</option>
<option value="4">长沙</option>
</select>
</div>
<!-- 导入 Vue 库文件,在 windows 全局就有了一个 Vue 的构造函数 -->
<script src="./lib/vue-2.6.12.js"></script>
<!-- 创建 Vue 实例对象 -->
<script>
// 创建 Vue 实例对象
const vm = new Vue({
// el 是固定的写法,表示 vm 要控制页面上的哪一个区域,接受的值是一个选择器
el:'#app',
// data 对象就是要渲染到页面上的数据
data:{
username:'zhangsan',
city:''
}
})
</script>
v-model 指令的修饰符
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-J4erLghq-1652883437025)(C:\Users\肖锦顺\AppData\Roaming\Typora\typora-user-images\1649826943490.png)]
v-show
的原理是:动态为元素添加或移除 display: none
样式,来实现元素的显示和隐藏
v-if
的原理是:每次动态创建或移除元素,实现元素的显示和隐藏
在实际开发中,绝大多数情况,不用考虑性能问题,直接使用 v-if 就好了!!!
v-if 指令在使用的时候,有两种方式:
直接给定一个布尔值 true 或 false
<p v-if="true">被 v-if 控制的元素p>
给 v-if 提供一个判断条件,根据判断的结果是 true 或 false,来控制元素的显示和隐藏
<p v-if="type === 'A'">良好p>
v-if 可以单独使用,也可以配合 v-else / v-else-if一起使用
<div v-if="type === A">
优秀
div>
<div v-else-if="type === B">
良好
div>
<div v-else-if="type === C">
一般
div>
<div v-else>
差
div>
vue 提供了 v-for 列表渲染指令
语法:v-for="(item,index) in list"
data: {
list: [ // 列表数据
{id: 1,name: 'zs'},
{id: 2,name: 'ls'}
]
}
// ------------------------------------
<ul>
<li v-for="item in list">姓名是:{{ item.name }}</li>
</ul>
注意:v-for 指令中的 item 和 index 都是形参,可以根据需要进行重命名。列如:(user,i) in userList
使用 key 维护列表状态
当列表数据发生变化时,默认情况下,vue 会尽可能的复用已经存在的 DOM 元素,从而提升渲染的性能。但这种默认的性能优化策略,会导有状态的列表无法被正确更新。
为了给 vue 一个提示,以便它能跟踪每个节点的身份,从而在保证有状态的列表被正确更新的前提下,提升渲染的性能。此时,需要为每项提供一个唯一的 key 属性
data: {
list: [ // 列表数据
{id: 1,name: 'zs'},
{id: 2,name: 'ls'}
]
}
// ------------------------------------
<ul>
// 为每项提供一个唯一的 key 属性
<li v-for="item in list" :key="item.id">姓名是:{{ item.name }}</li>
</ul>
key 的注意事项
过滤器(Filters)常用于文本的格式化。过滤器可以用在两个地方:插值表达式和 v-bind 属性绑定
过滤器应该被添加在 JavaScript 表达式的尾部,由“管道符”进行调用
<div id="app">
<p>message的值是:{{ message | cpi}}p>
div>
<script src="./lib/vue-2.6.12.js">script>
<script>
const vm = new Vue({
el:'#app',
data:{
message:'hello Vue.js',
},
// 过滤器函数必须定义到 filters 节点之下
// 过滤器实质上也是一个函数
filters:{
// 注意,过滤器函数形参 val 是管道符 "|"前面的那个数据
cpi(val){
// 字符串有 charAt 方法,这个方法接受所索引值,表示在字符串中把索引对应的字符取出来
// 第一个字符 val.charAt(0)
const first = val.charAt(0).toUpperCase()
// 字符串的 slice 方法,可以截取字符串,从指定索引往后截取
const other = val.slice(1)
// 强调,过滤器必须要有返回值
return first + other
}
}
})
私有过滤器和全局过滤器
在 filters 节点下定义的过滤器。称为“私有过滤器”。Vue.filter() 定义全局过滤器
<div id="app">
<!-- 代用过滤器 " | "叫做管道符 -->
<p>message的值是:{{ message | cpi}}</p>
</div>
<div id="app1">
<!-- 代用过滤器 " | "叫做管道符 -->
<p>message的值是:{{ message | cpi}}</p>
</div>
<script src="./lib/vue-2.6.12.js"></script>
<script>
// 使用 Vue.filter() 定义全局过滤器
// 两个参数:一个过滤器函数名称,一个函数
// 如果 全局过滤器 和 私有过滤器 名字冲突,就近原则会先调用 私有过滤器
Vue.filter('cpi',function(val){
const first = val.charAt(0).toUpperCase()
const other = val.slice(1)
return first + other
})
const vm = new Vue({
el:'#app',
data:{
message:'hello Vue.js',
},
// 过滤器函数必须定义到 filters 节点之下
// 过滤器实质上也是一个函数
filters:{
// 这里定义的是私有过滤器
// 注意,过滤器函数形参 val 是管道符 "|"前面的那个知
cpi(val){
// 字符串有 charAt 方法,这个方法接受所索引值,表示在字符串中把索引对应的字符取出来
// 第一个字符 val.charAt(0)
const first = val.charAt(0).toUpperCase()
// 字符串的 slice 方法,可以截取字符串,从指定索引往后截取
const other = val.slice(1)
// 强调,过滤器必须要有返回值
return first + other
}
}
})
const vm1 = new Vue({
el:'#app1',
data:{
message:'xjs',
}
})
连续调用多个过滤器
/*
把 message 的值,交给 filterA 进行处理
把 filterA 处理的结果交给 filterB 进行处理
最后把 filterB 处理的结果,作为最终值渲染都页面上
*/
{{ message | fliterA | filterB}}
过滤器传参
过滤器的本质是 JavaScript 函数,因此可以接受参数
// 传递参数
<p>{{ messgae | filterA(arg1,arg2)}}</p>
// 第一个参数,永远都是 “管道符” 前面待处理的值
// 从第二个参数开始,才是接受传递过来的参数
Vue.filter('filterA',(message,arg1.arg2) => {
// 逻辑代码
})
watch 侦听器允许开发者监听数据的变化,从而针对数据的变化做特定的操作
const vm = new Vue({
el: '#app',
data: {
username: 'xjs'
},
watch: {
// 监听 username 值的变化
// newVal 是变化之后的值 oldVal 是变化之前的值
username(newVal,oldVal) {
console.log(newVal,odlVal)
}
}
})
默认情况下,组件初次加载完毕后不会调用 watch 侦听器。如果想让 watch 侦听器立即被调用,则需要使用 immediate 选项
const vm = new Vue({
el: '#app',
data: {
username: 'xjs'
},
watch: {
// 监听 username 值的变化
// newVal 是变化之后的值 oldVal 是变化之前的值
username(newVal,oldVal) {
console.log(newVal,odlVal)
},
// 表示页面初次渲染之后,就立即触发当前的侦听器
immediate: true
}
})
如果 watch 侦听的是一个对象,如果对象中的属性值发生了变化,则无法被监听到。此时需要使用 deep 选线
const vm = new Vue({
el: '#app',
data: {
info: {
username: 'xjs',
age: 18
}
},
watch: {
// 监听 username 值的变化
// newVal 是变化之后的值 oldVal 是变化之前的值
info(newVal,oldVal) {
console.log(newVal.username,odlVal.username)
},
// 深度监听
deep: true
// 或者之间监听子属性
// 监听对象子属性的变化,需要在外面包裹一层单引号
'info.username'(newVal){
console.log(newVal)
}
}
})
计算属性指定是通过一系列运算之后,最终得到的一个属性值
这个动态计算出来的属性值可以被模板结构或 methods 方法使用
<div id="app">
<div>
<span>R:</span>
<input type="text" v-model.number="r">
</div>
<div>
<span>G:</span>
<input type="text" v-model.number="g">
</div>
<div>
<span>B:</span>
<input type="text" v-model.number="b">
</div>
<hr>
<!-- 专门用户呈现颜色的 div 盒子 -->
<!-- 在属性身上,: 代表 v-bind: 属性绑定 -->
<!-- :style 代表动态绑定一个样式对象,它的值是一个 { } 样式对象 -->
<!-- 当前的样式对象中,只包含 backgroundColor 背景颜色 -->
<div class="box" :style="{ backgroundColor: rgb }">
{{ rgb }}
</div>
<button @click="show">按钮</button>
</div>
<script>
// 创建 Vue 实例,得到 ViewModel
var vm = new Vue({
el: '#app',
data: {
// 红色
r: 0,
// 绿色
g: 0,
// 蓝色
b: 0
},
methods: {
// 点击按钮,在终端显示最新的颜色
show() {
console.log(this.rgb)
}
},
// 所有的计算属性都要放在 computed 节点下
// 计算属性在定义的时候,要定义成 “方法格式”
computed:{
// rgb 作为计算属性,被定义成了一个方法格式
// 最终在这个方法中要返回一个拼接号的 rgb(x,x,x) 字符串
// 计算属性在定义的时候被定义成 “方法格式”,
// 使用的时候作为 属性使用
rgb() {
return (`rgb(${this.r},${this.g},${this.b})`)
}
}
});
</script>