一、MVVM模式
1、设计模式流程图
2、ViewModel的本质
ViewModel定义了一个Observer观察者(发布订阅模式)
- ViewModel能观察到数据的变化,并对视图对应的内容进行更新
- ViewModel能监听到数据的变化,并能够通知数据发生改变
3、MVVM设计模式的特点:
MVVM最重要的就是实现了View和Model的自动同步,所以可以不用频繁地手动操作DOM元素 •
- 核心:数据劫持 + 发布订阅模式 •
- Vue.js就是一个MVVM的实现者,其核心就是DOM监听和数据绑定
二、模板语法
1、插值语法
①表达式:
在模板中,{{}}还可以用来写一些javascript表达式,表达式是js的 单行非赋值语句,每个表达式都有返回值,表达式可以直接使用组件属性、方 法、计算属性等。
②插值语法:
用于在模板中的数据绑定,语法格式是“{{msg}}” ,模板中的变量 可以在data中定义,当data中的变量改变时,插值处的内容也会随之更新。
2、内容指令
① 指令(Directives):
带有v-前缀的特殊标签属性。本质上是一段ES程序,该 程序通过标签属性声明,与java中的标签库类似。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>主页</title>
<script src="js/vue.js"></script>
</head>
<body>
<div id="app">
<!-- {{
使用 JavaScript 表达式:逻辑运算、三元运算、字符串操作
}}
这是语句,不是表达式
{{ var a = 1 }}
流控制也不会生效,请使用三元表达式
{{ if (ok) { return message } } }
-->
{{1+1}}<br/>
{{city? "ningbo":"shanghai"}}<br/>
{{"ABCD".split("")}}<br/>
{{ message }}<br/>
This is {{info}}<br/>
<label>
<input v-focus />
</label>
</div>
<script>
// 注册一个全局自定义指令 `v-focus`
Vue.directive('focus',{
// 当被绑定的元素插入到 DOM 中时……
inserted:function (el) {
// 聚焦元素
el.focus();
}
});
//let局部变量,var全局变量
let app= //可以不写
new Vue( //new Vue函数
{
el: '#app', //一个vue应挂载到一个DOM元素上,也表示vue的作用范围
data: //vue实例对象内的数据,可以有多个数据
{
message: 'Hello Vue!',
info:"china faw",
city : false
}
});
</script>
</body>
</html>
②内容指令:
用于声明当前dom元素内的文本或dom内容。
• v-text:用于更新元素的textContent(文本内容)
• v-html:用于更新元素的innerHTML,内容按普通html插入,不会作为vue模板进行编译
• v-once:用于修饰静态内容,指令的子元素只会在初始化时更新一次,不会重新渲染。
<body>
<div id="app">
{{message}}<br/>
<!-- • 内容指令:用于声明当前dom元素内的文本或dom内容。-->
<!-- • v-text:用于更新元素的textContent(文本内容)-->
<!-- • v-html:用于更新元素的innerHTML,内容按普通html插入,不会作为vue模板进行编译-->
<!-- • v-once:用于修饰静态内容,指令的子元素只会在初始化时更新一次,不会重新渲染。-->
<p v-text="v1">这是p标签</p>
<p v-html="v2">这是div标签</p>
<p v-once>{{v3}}</p>
</div>
<script>
//let局部变量,var全局变量,const常量
let app= //可以不写
new Vue( //new Vue函数
{
el: '#app', //一个vue应挂载到一个DOM元素上,也表示vue的作用范围
data: //vue内的数据,可以有多个数据
{
message: 'Hello Vue!',
v1:'<span>V1</span>',
v2:'<span style="color:red">V2</span>',
v3 : 'V3'
}
});
</script>
</body>
③流程控制指令
v-show、v-if、v-for
<body>
<div id="app">
<!-- v-show:条件渲染,根据表达式真假,通过元素的display属性控制元素是否显示-->
<h1 v-show="v1">Hello!</h1>
<!-- v-if:根据表达式真假条件渲染元素,在切换时元素被销毁并重建,可以和v-else、velse-if一起用-->
<div v-if="type === 'A'">A</div>
<div v-else-if="type === 'B'">B</div>
<!-- <div>123</div>-->
<!-- 中间插入其他元素v-if会被打断 -->
<div v-else-if="type === 'C'">C</div>
<div v-else>Not A/B/C</div>
<!-- 我们可以用 v-for 指令基于一个数组来渲染一个列表。v-for 指令需要使用 item in items 形式的特殊语法,-->
<!-- 其中 items 是源数据数组,而 item 则是被迭代的数组元素的别名。-->
<div v-for="(value,index) in arr1">
索引:{{index}} 值:{{value}}
</div>
<hr/>
<!-- item可以是对象-->
<div v-for="(person,index) in arr2">
索引:{{index}} 姓名:{{person.name}} 年龄:{{person.age}}
</div>
<hr/>
<!-- items可以是对象-->
<div v-for="(value,key,index) in arr3">
索引:{{index}} 属性:{{key}} 值:{{value}}
</div>
<hr/>
<!-- item可以是数字-->
<div v-for="count in 5">
{{count}}
</div>
</div>
<script>
new Vue( //new Vue函数
{
el: '#app', //一个vue应挂载到一个DOM元素上,也表示vue的作用范围
data: //vue内的数据,可以有多个数据
{
v1:true,
type :'E',
arr1:[1,2,3,4,5],
arr2:[{name : '李雷', age :20},{name : '韩梅梅', age :18}],
arr3:{id :'007', name:'詹姆斯邦德'},
}
});
</script>
</body>
④属性与样式设定
VUE中使用v-bind指令绑定属性以及样式。
• 绑定后dom元素的属性与样式取值与绑定的表达式计算结果一致
• 绑定的数据类型是字符串。
• 在绑定style或class时,也可以是对象或数组类型
<body>
<div id="app">
<!-- 直接把值绑定到确定的属性上-->
<a v-bind:href="url">{{name}}</a><br/>
<!-- 绑定数据属性可以参与计算-->
<a v-bind:href="url+https">{{name}}</a><br/>
<!-- 绑定值到动态属性上-->
<a v-bind:[attr]="url">{{name}}</a>
<!-- 样式绑定-->
<div v-bind:class="{'red':showRed,'green':showGreen}">长春加油</div>
<!-- 样式绑定——值可以是数组-->
<div v-bind:class="arr">长春加油</div>
<div v-bind:style="{fontSize:size,color:gen}">长春加油</div>
</div>
<script>
new Vue({
el : "#app",
data:{
name:"百度",
url : "https://www.baidu.com",
https:"/s?wd=vue",
attr: "href",
showRed:true,
showGreen:false,
arr:['red','green'],
size:'40px',
gen:'green',
}
})
</script>
</body>
⑤事件监听
• 事件监听:监控用户的特定操作行为,执行开发者响应程序。
• 配置用户交互的响应函数的方式
• 事件属性配置响应函数
• 调用事件监控api配置响应函数
vue响应函数:在vue中使用methods属性声明vue全局或组件实例对象的内部函数。methods属性为对象类型,内部的函数作用如下:
• 事件响应函数
• 实例私有函数
• 模板调用函数(使用计算属性替换)
多响应函数绑定:当dom对象绑定了多个响应函数,会依据绑定顺序依次执行响应函数
响应函数传参:可以通过函数调用的方式给响应函数传递参数
- 无参数响应函数可以接收事件参数event,event为dom事件对象。
- 可通过函数调用传递参数,参数可以为data属性中的数据。
- $event代表event事件对象。
<body>
<div id="app">
<div>
{{msg}}
<!-- 绑定事件-->
<div>账号:<input /></div>
<div>密码:<input type="password"/></div>
<div><button v-on:click="login">登录</button></div>
<!-- 用@简写-->
<div><button @click="reg">注册</button></div>
<div><button @click="login($event)">登录</button></div>
</div>
</div>
<script>
new Vue({
el : "#app",
data:{
msg:'欢迎'
},
methods : {
login:function(e) {
console.info('登录')
console.info(e.target.innerText)
// 改变data的值
this.msg='登录'
},
// 简写
reg(){
console.info('注册')
}
}
})
</script>
</body>
事件修饰符:用于在事件处理函数中,快捷地处理常见的一些细节操作。语法:是以点开头的指令后缀。
- 基础事件修饰符
- 按键修饰符
<body>
<div id="app">
<!-- 事件的传递由内向外(一般传递过程中执行),事件的捕获由外到内-->
<!-- stop:阻止事件传递-->
<!-- m1 capture:捕获后立即触发-->
<div @click.capture="m('m1')" style="width: 400px;height: 400px;background-color: red">
<!-- m2 stop:不会向外传递-->
<div @click.stop="m('m2')" style="width: 200px;height: 200px;background-color: green">
<div @click.self="m('m3')" style="width: 100px;height: 100px;background-color: blue"></div>
</div>
</div>
<!-- prevent:取消默认事件,取消a标签的跳转-->
<!-- passive:对默认事件优化-->
<a href="https://www.baidu.com" @click.prevent="m('baidu')">百度</a>
<!-- self:只在当前范围触发 ex:点m3输出m3、m1;点m2输出m2、m1;点m1输出m1-->
<div @click="m('m1')" style="width: 400px;height: 400px;background-color: red">
<div @click.self="m('m2')" style="width: 200px;height: 200px;background-color: green">
<!-- once:只执行一次-->
<div @click.once="m('m3')" style="width: 100px;height: 100px;background-color: blue"></div>
</div>
</div>
</div>
<script>
new Vue({
el:'#app',
methods : {
m(title){
console.info(title);
}
}
})
</script>
</body>
<body>
<div id="app">
<div>账号:<input /></div>
<!-- keyup.enter按下回车键时响应函数触发-->
<!-- keyup.tab按下tab键时响应函数触发
触发光标指向的元素触发,上一个元素按tab,下一个元素触发响应函数 -->
<!-- delete:删除、退格键-->
<!-- esc:退出键-->
<!-- right:向右键-->
<!-- space:空格键-->
<!-- up:向上键-->
<!-- down:向下键-->
<!-- left:向左键-->
<div>密码:<input @keyup.enter="m('回车')" @keyup.tab="m('tab')" type="password"/></div>
</div>
<script>
new Vue({
el:'#app',
methods : {
m(title){
console.info(title);
}
}
})
</script>
</body>
⑥v-model指令
该指令可以对表单元素与data中的数据做双向绑定。即表单标签的内容与绑定的vue实例中的属性双向同步
v-model指令原理分析:
• dom到data的数据同步:依靠dom节点的数据变化事件类型捕获输入改变,动态修改data中的数据。
• data到dom的数据同步:
• 对不同的标签类型进行分类
• 初始化编译时将v-model设定的字符类型的表达式以props属性的方式写入到dom对象中。
• 在数据变化时触发更新dom操作,在更新dom时遍历所有props属性并获取实际取值最终赋值。
<body>
<div id="app">
<div>学号:<input v-model="sid"/></div>
<div>姓名:<input v-model="name"/></div>
<div>性别:男<input v-model="sexCheck" value="男" type="radio" name="sex"/>女<input v-model="sexCheck" value="女" type="radio" name="sex"/></div>
<div>民族:<select v-model="nationSelect"><option v-for="(value) in nation">{{value}}</option></select></div>
<div>爱好:<span v-for="(value) in hobby"><input type="checkbox" v-bind:value="value" v-model="hobbyCheck"/>{{value}}</span></div>
<div>简介:<textarea v-model="demo"></textarea></div>
<div><button @click="pull">获取</button><button @click="push">写入</button></div>
</div>
<script>
new Vue({
el:'#app',
data : {
sid:'',
name : '',
sex : '',
sexCheck:'',
nation:['汉','满','壮'],
nationSelect:'',
hobby : ['篮球', '足球'],
hobbyCheck : [],
demo:''
},
methods : {
pull(){
console.info(this.sid+this.name+this.sexCheck+this.nationSelect+this.hobbyCheck+this.demo)
},
push(){
this.sid='001';
this.name='tom';
this.sexCheck='男';
this.nationSelect='汉';
this.hobbyCheck=['篮球'];
this.demo='非常帅气';
}
}
})
</script>
</body>
三、Vue实例对象
①dom选项
vue的dom:用于将vue与指定的Dom结构绑定的配置选项。
②模板语法
<body>
<div id="app">
宁波加油
</div>
<script>
new Vue({
//el属性指定当前Vue实例对象渲染的Dom节点。
//el的取值可以采用id选择器或类选择器两种方式赋值
// el的取值也可以是指定dom节点的dom对象。
el:'#app',
// 替换dom节点,当使用template属性时,Dom区域的内容将会被覆盖
template:`<div>长春加油{{msg}}
<br>
宁波加油!
</div>`,
//使用js接口构建dom结构,createElement参数说明
// param1:标签名
// param2:当前dom的属性设定,可以通过style、class设定样式。
// params:数组类型,当前dom结构的子元素。
render(createElment){
return createElment('h1',{style:'background:red'},'长春加油')
},
data:{
msg:'!'
}
})
</script>
</body>
③观察属性
观察属性:又称为监听属性,会监听当前实例对象或组件对象的数据属性,当 数据变化时观察属性配置的响函数将会被触发。一般监控如下属性
- data属性
- props属性
<body>
<div id="app">
账号:<input v-model="userId">
</div>
<script>
new Vue({
el : "#app",
data : {
userId:"",
firstName : "",
lastName : ""
},
//监听当前实例对象或组件对象的数据属性,当数据变化时观察属性配置的响应函数将会被触发
//不能监听数组长度改变
watch : {
//监听属性完全体
// handler数据变化后的响应函数,参数分别时变化前的参数和变化后的参数
//deep:当监控的数据为对象类型时,修改数据属性(对象的栈内存地址不变)是否需要监控。
//immediate:首次赋值时是否需要监控。
userId: {
handler(newValue, oldValue) {
console.log(oldValue);
console.log(newValue);
},
deep: true,
Immediate: true,
},
userId:function(newValue,oldValue) {
console.log(oldValue)
console.log(newValue);
}
}
});
</script>
</body>
④计算属性
computed:计算属性,用于处理页面的复杂逻辑
- Vue的表达式仅支持三目运算符和比较运算符之类的简单逻辑,不支持条件控制语句等复杂逻辑。
- 在computed中,Vue会记住计算属性所依赖的值,只有在依赖发生改变的时候才会计算值,否则,将返回计算属性所依赖的值。
- 计算属性中的函数在每次页面渲染时都会执行,不管数据是否发生改变。
<body>
<div id="app">
姓:<input v-model="firstName">名:<input v-model="lastName">全名:{{fullName}}
</div>
<script>
//在computed中,Vue会记住计算属性所依赖的值,只有在依赖发生改变的时候才会计算值,否则,将返回计算属性所依赖的值
let vm=new Vue({
el : "#app",
data : {
firstName : "",
lastName:"",
//fullName:"" fullName是计算属性,不要在data中定义
},
computed:{
//默认情况下,function为fullName的get方法,也就是赋值方法
//简写体
// fullName:function() {
// return this.firstName+this.lastName;
// }
fullName:{
//当给fullName赋值时触发,用到的并不多,基本上都是简写的形式。
set : function (val) {
let data=val.split('.')
this.firstName=data[0];
this.lastName = data[1];
},
get : function() {
return this.firstName+this.lastName;
}
}
}
});
vm.fullName='李.雷';
</script>
</body>