数据驱动视图
数据的变化会驱动视图自动更新
好处:程序员只把数据维护好,那么页面结构会被Vue自动渲染出来。
在网页中,form表单负责采集数据,Ajax负责提交数。
js数据的变化,会被自动渲染到页面上
页面上表单采集的数据发生变化的时候,会被Vue自动获取,并更新到js数据中。
注意: 数据驱动视图和双向绑定的底层原量是MVVM(Model数据源、View视图、ViewModel。其中,ViewModel 是Vue的实例)
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>Documenttitle>
<script src="lib/vue-2.6.12.js">script>
head>
<body>
<div id="app">
div>
<script>
//创建Vue的实例
const vm = new Vue({
// el属性是固定写法。
// 表示当前的VM实例要控制页面上的哪上区域,收接的是一个选择器。
el: "#app" ,
data:{
username:"zhangsan",
}
})
script>
body>
html>
**指令(Directives)**是Vue为开发者提供的 模板语法,用于 辅助开发者渲染页面的基本结构。
Vue中的指令按照不同的用途,可分为6大类:
指令是Vue开发中最基础、最常吸入、最简单的知识点。
内容渲染指令 用来辅助开发者 渲染 DOM 元素的文本内容 。常用的内容渲染指令有如下3 个:
v-text
<p v-text="username">p>
<p v-text="gender">性别p>
缺点:
v-text
指令会覆 盖标签内部原本的内容,缺点很明显,实际使用少。
{{ }}
:插值表达式vue 提供的 {{ }}
语法,专门用来解决 v-text
会覆盖默认文本内容的问题。这种 {{ }}
语法的专业名称是 插值表达式
(英文名为:Mustache)。
姓名:{{username}}
性别:{{gender}}
插值表达式
,只是内容的占位符,实际开发中使用最多。
只有用在内容节点,无法用在属性节点。
v-html
在vue中,可以使用v-bind:
指令,为元素的属性动态绑定值。
简写是:
。
v-bind:
与插值表达式
的区别?
插值表达式
只能用在 内容节点,无法用在属性节点。
v-bind:
用于为元素的属性动态绑定值。
示例:
<img v-bind:src="vueImg" />
<hr>
VUE规定v-bind指定可简写<br>
<img :src="vueImg" />
<script>
//创建Vue的实例
const vm = new Vue({
// el属性是固定写法。
// 表示当前的VM实例要控制页面上的哪上区域,收接的是一个选择器。
el: "#app" ,
data:{
vueImg:"./images/vue.jpg"
}
})
script>
<div id="app">
num=25+10
表达式计算: {{num +10}}
<hr>
num2=25+20
<input type="text" v-bind:placeholder="num2 + 20" >
num2=25+ '-20'
<input type="text" v-bind:placeholder="num2 + '-20'" >
div>
<script>
//创建Vue的实例
const vm = new Vue({
el: "#app" ,
data:{
num: 25,
num2: 25,
}
})
script>
vue 提供了 v-on
事件绑定指令,用来辅助程序员为DOM 元素绑定事件监听。
v-on
简写 @
。如 v-on:click
可简写成 @click
。
常见的原生DOM 事件有 onclick
、oninput
、onkeyup
,替换为vue 的事件, 分别为:v-on:click
、v-on:input
、v-on:keyup
。
以 v-on:click
为例,v-on:click
简写成 @click
。 语法格式如下:
<p> count 的值是{{ count }}p>
<button v-on:click="add"> +1 button>
示例:
<div id="app">
<p> count 的值是{{ count }}p>
<button v-on:click="add"> +1 button>
<button v-on:click="sub"> -1 button>
div>
<script>
//创建Vue的实例
const vm = new Vue({
// el属性是固定写法。
// 表示当前的VM实例要控制页面上的哪上区域,收接的是一个选择器。
el: "#app" ,
data:{
count: 0,
},
// methods的作用,就是定义事件的处理函数
methods:{
add{
vm.count+=1
console.log(vm==this)
console.log(vm)
},
sub(){
this.count-=1
},
}
})
script>
运行上面的代码,得到 vm
等于 this
,一般使用this
。
add
函数接收参数
<div id="app">
<p> count 的值是{{ count }}p>
<button @:click="add(2)"> +1 button>
<button v-on:click="sub"> -1 button>
div>
<script>
//创建Vue的实例
const vm = new Vue({
// el属性是固定写法。
// 表示当前的VM实例要控制页面上的哪上区域,收接的是一个选择器。
el: "#app" ,
data:{
count: 0,
},
// methods的作用,就是定义事件的处理函数
methods:{
add(n){
this.count+=n
console.log(vm)
},
sub(){
this.count-=1
},
}
})
script>
v-on:click
简写成 @click
<div id="app">
<p> count 的值是{{ count }}p>
<button @click="add(2)"> +1 button>
<button @click="sub"> -1 button>
div>
<script>
//创建Vue的实例
const vm = new Vue({
// el属性是固定写法。
// 表示当前的VM实例要控制页面上的哪上区域,收接的是一个选择器。
el: "#app" ,
data:{
count: 0,
},
// methods的作用,就是定义事件的处理函数
methods:{
add(n){
this.count+=n
console.log(vm)
},
sub(){
this.count-=1
},
}
})
script>
<div id="app">
<p> count 的值是{{ count }}p>
<button @click="add(2,$event)"> +1 button>
div>
<script>
const vm = new Vue({
el: "#app" ,
data:{
count: 0,
},
methods:{
add(n,event){
this.count+=1
// console.log(e)
if(this.count%2==0){
event.target.style='background-color:red;'
}else{
event.target.style=''
}
},
sub(){
this.count-=1
},
}
})
script>
件修饰符 | 说明 |
---|---|
.prevent | 阻止默认行为 (例如:阻止a 连接的跳转、阻止表单的提交等) |
.stop | 阻止事件冒泡 |
.capture | 以捕获模式触发当前的事件处理函数 |
.once | 绑定的事件只触发1次 |
.self | 只有在 event.target 是当前元素自身时触发事件处理函数 |
@click.prevent
<a href="http://www.baidu.com" @click.prevent="show" >跳转到百度首页a>
@click.stop
<div style="height:150px;background-color:orange;" @click="divHander">
<button @click.stop="btnHander">按钮事件button>
div>
在 监听键盘事件 时,我们经常需要 判断详细的按键。此时,可以为 键盘相关的事件 添加 按键修饰符。
.esc
、 .enter
v-model
双向数据绑定指令vue 提供了 v-model
双向数据绑定指令,用来辅助开发者在不操作DOM 的前提下,快速获取表单的数据。
只有表单数据 才能使用 v-model
指令:
<div id="app">
<p>用户名是 {{username}}p>
<input type="text" v-model="username">
div>
<script>
const vm = new Vue({
el: "#app" ,
data:{
username:'zhangsan',
},
})
script>
示例2:(select 双向绑定)
<div id="app">
<p>选中的省份是 {{province}}p>
<p>
<input type="text" v-model="province">
p>
<select v-model="province">
<option>请选择option>
<option value="1">北京option>
<option value="2">河北option>
<option value="3">黑龙江option>
select>
div>
<script>
const vm = new Vue({
el: "#app" ,
data:{
province:'',
},
})
script>
v-model
与 v-bind:
的区别说明:
v-model
是双向绑定 ,v-bind:
是单向绑定 。
<div id="app">
<p>用户名是 {{username}}p>
<input type="text" v-model="username">
<p>用户名(v-bind)是 p>
<input type="text" :value="username">
div>
<script>
const vm = new Vue({
el: "#app" ,
data:{
username:'zhangsan',
},
})
script>
v-model
指令的修饰符修饰符 | 作用 | 示例 |
---|---|---|
.number | 自动将用户的输入值转为 数值类型 | |
.trim | 自动过滤用户输入的 首尾 空白字符 |
|
.lazy | 在“change”时而非“input”时更新 |
|
示例:
不使用 .number
时是字符串拼接,加上 .number
是数值相加。
<div id="app">
<input type="text" v-model.number="n1">
+
<input type="text" v-model.number="n2">
<p>
{{ n1 + n2 }}
p>
div>
<script>
const vm = new Vue({
el: "#app" ,
data:{
n1:0,
n2:0,
},
})
script>
条件渲染指令用来辅助开发者按需控制DOM 的显示与隐藏。条件渲染指令有如下两个,分别是:
v-if
v-show
实现原理不同:
v-if
指令会动态地创建或移除DOM 元素,从而控制元素在页面上的显示与隐藏;
v-show
指令会动态为元素添加或移除 style="display: none;"
样式,从而控制元素的显示与隐藏。
性能消耗不同:
v-if
有更高的切换开销,而 v-show
有更高的初始渲染开销。因此:
如果需要非常频繁地切换,则使用 v-show
较好 。
如果在运行时条件很少改变,则使用 v-if
较好 。
v-if
v-else-if
v-else
组合<p>
<div v-if="type ==='A'">优秀div>
<div v-else-if="type ==='B'">良好div>
<div v-else-if="type ==='C'">一般div>
<div v-else>差div>
p>
vue 提供了v-for
循环渲染指令,用来辅助开发者基于一个数组来循环渲染一个列表结构。v-for
指令需要使
用 item in items
形式的特殊语法,其中:
items
是待循环的数组。item
是被循环的每一项。v-for
指令,一定要绑定一个 :key
属性,:key
属性的值必须是唯一的。<div id="app">
<p>
id: <input type="text" name="id" id="id" v-model="id">
name: <input type="text" name="idname" id="name" v-model="name">
<button @click="add">添加对象button>
p>
<ul>
<li v-for="(item,index) in list" :key="item.id" >
索引是{{index}},姓名是{{item.name}}
li>
ul>
div>
<script>
const vm = new Vue({
el: "#app" ,
data:{
id:"",
name:"",
list:[
{id:1,name:"zhangsan"},
{id:2,name:"lisi"},
{id:3,name:"wangwu"},
]
},
methods:{
add(){
var item={"id":this.id,"name":this.name};
console.log(item)
this.list.push(item)
this.id="";
this.name="";
}
}
})
script>
① key 的值只能是 字符串 或 数字 类型
② key 的值必须具有 唯一性(即:key 的值不能重复)
③ 建议把 数据项id 属性的值 作为key 的值(因为id 属性的值具有 唯一性)
④ 使用 index 的值当作key 的值 没有任何意义(因为index 的值不具有唯一性)
⑤ 建议使用 v-for
指令时 一定要指定key 的值(既提升性能、又防止列表状态紊乱)
<ul>
<li v-for="(item,index) in list" :key="item.id" :title="'title-'+item.id" :index="'index-'+index" >
索引是{{index}},姓名是{{item.name}}
li>
ul>
Filters : 只存在于 Vue2 ,Vue3 已没有过滤器。
过滤器 (Filters)是vue 为开发者提供的功能,常用于文本的格式化。
过滤器可以用在两个地方:插值表达式 {{ }}
和 v-bind
属性绑定。
过滤器 应该被添加在 JavaScript 表达式的 尾部,由 管道符
进行调用,示例代码如下:
<p>{{ message | capitalize }}p>
<div v-bind:id="rawId | formatId" >div>
<div id="app">
<div>{{message | capi}}div>
div>
<script src="./lib/vue-2.6.12.js">script>
<script type="text/javascript">
const vm =new Vue({
"el":"#app",
filters:{
// 注意:过虑器函数形参中的val,永远都是“管道符”前面的那个值
capi(val){
// 强调,过滤器中,一定要有一个返回值
const first=val.charAt(0).toUpperCase()
const other = val.slice(1)
return first+""+other;
}
}
});
script>
全局过滤器:在filters 节点下定义的过滤器,称为 私有过滤器, 因为它 只能在当前vm 实例所控制的 el 区域内使用。 如上一个示例。
全局过滤器:如果希望在多个vue 实例之间共享过滤器,则定义全局过滤器。格式如下
<div id="app">
<div>{{message | capi2}}div>
div>
<script src="./lib/vue-2.6.12.js">script>
<script type="text/javascript">
// Vue.fiter() 接收两个参数:
// 第1个参数,全局过滤器的 “名称”
// 第2个参数,全避过滤器的 “处理函数”
Vue.filter('capi2',(str)=>{
const first=str.charAt(0).toUpperCase()
const other = str.slice(1)
return first+""+other;
})
const vm =new Vue({
"el":"#app",
data:{
message:"hello vue.js",
},
filters:{
// 注意:过虑器函数形参中的val,永远都是“管道符”前面的那个值
capi(val){
// 强调,过滤器中,一定要有一个返回值
const first=val.charAt(0).toUpperCase()
const other = val.slice(1)
return first+""+other;
}
}
})
script>
<div id="app">
<div>{{message | filterA( arg1 ,arg2) }}div>
div>
<script src="./lib/vue-2.6.12.js">script>
<script type="text/javascript">
// fiter() 函数的形参 列表中
// 第1个参数,永远都是“管道符”前面待处理的值
// 第第2个参数开始,才是调用过滤器时传递过来的arg1,argument参数
Vue.filter('capi2',(msg , arg1 , arg2)=>{
...省略...
});
script>
watch监听器公允开发者监听数据的变化,从而针对数据的变化做出特定的操作。
语法格式:
<div id="app">
<input type="text" v-model="username" >
div>
<script type="text/javascript">
const vm =new Vue({
"el":"#app",
data:{
username:'',
},
watch:{
// 监听 username 值的变化
// newVal是变化后的新值,oldVal是变化之前的旧值
username(newVal,oldVal){
console.log(newVal +" , "+oldVal)
}
}
})
script>
注意事项:
v-model
。方法格式的监听器
username
时, 格式是 username(newVal,oldVal)
。对象格式的监听器
username
时, 格式是 username:{ ... }
。immediate
选项,让 监听器 自动触发 监听(就是立即监听)。deep
选项,让 监听器 深度监听。方法格式:
username(newVal,oldVal){
//...
}
对象格式:
username:{
handler(newVal,oldVal){
//...
},
deep: true,
immediate: true,
}
下面是改成 对象格式 的相关示例。
默认情况下,组件在初次加载完毕后,不会调 用 watch
监听器。
如果想让 watch 监听器立即被调用,则用 immediate
选项。
<div id="app">
<input type="text" v-model="username" >
div>
<script type="text/javascript">
const vm =new Vue({
"el":"#app",
data:{
username:'',
},
watch:{
// 此处是对象格式的监听
username:{
// handler 是固定写法,表示当username的值变化时,自动调用 handler函数
handler: function(newVal ,oldVal) {
console.log(newVal +" , "+oldVal)
// ... 其它操作省略
},
// 表示页面渲染好之后,就立即触发当前的watch监听器
immediate: true,
}
}
})
script>
说明:
handler: function(newVal ,oldVal)
的简写是 handler (newVal ,oldVal)
。如果watch 监听的是一个 对象,如果 对象中的属性值 发生了变化,则无法被监听到, 必须使用 deep
才能监听到。
<script type="text/javascript">
const vm =new Vue({
"el":"#app",
data:{
info:{username:'admin'}
},
watch:{
// 对象格式的监听,监听对象的所有属性值的变化
info:{
// handler 是固定写法,
handler(newVal){
console.log(newVal)
},
deep: true
},
}
})
script>
监听对象时的必须配置:
<script type="text/javascript">
const vm =new Vue({
"el":"#app",
data:{
info:{username:'admin'}
},
watch:{
// 对象格式的监听,监听对象的单个属性值
'info.username':{
// handler 是固定写法,
handler(newVal){
console.log(newVal);
},
},
}
})
script>
监听对象时的必须配置:
计算属性指的是 通过一系列运算 之后,最终得到一个 属性值。
这个动态计算出来的属性值 可以被模板结构或methods 方法使用。
没有使用 计算属性 前的代码:
<div id="app">
Red: <input type="text" v-model="r" > <br>
Green: <input type="text" v-model="g" > <br>
Blue: <input type="text" v-model="b" > <br>
<div class="box" :style="{ backgroundColor:`rgb(${r},${g},${b})` }" >
{{ `rgb( ${r},${g},${b} )` }}
div>
<button @click="show">按钮button>
div>
<script src="./lib/vue-2.6.12.js">script>
<script type="text/javascript">
const vm =new Vue({
"el":"#app",
data:{
r:0,
g:0,
b:0,
},
methods:{
// 点击按钮,在终端显示最新的颜色
show(){
console.log(`rgb(${this.r},${this.g},${this.b})`)
}
}
})
script>
使用 计算属性 的代码
<div id="app">
Red: <input type="text" v-model="r" > <br>
Green: <input type="text" v-model="g" > <br>
Blue: <input type="text" v-model="b" > <br>
<div class="box" :style="{ backgroundColor: rgb }" >
{{ rgb }}
div>
<button @click="show">按钮button>
div>
<script src="./lib/vue-2.6.12.js">script>
<script type="text/javascript">
const vm =new Vue({
"el":"#app",
data:{
r:0,
g:0,
b:0,
},
// 所有的计算属性,都要定义到computed 节点下。
//计算属性在定义的时候,要定义成 "方法格式"
computed:{
// rgb作为一个计算属性,被定义成方法格式
// 最终,在这个方法中,要返回一个生成好的 rgb(x,x,x) 的字符串
rgb(){
return `rgb( ${this.r} ,${this.g} ,${this.b} )`
}
},
methods:{
// 点击按钮,在终端显示最新的颜色
show(){
console.log( this.rgb )
}
}
})
script>
特点:
所有的计算属性,都要定义到 computed 节点下。
计算属性在定义的时候,要定义成 “方法格式” 。
好处: