Vue入门3、MVVM+虚拟DOM+绑定+如何在console里调用vue组件属性+双向绑定
MVVM
我们直接从网上找来一张图
需要注意的是,ViewModel所封装出来的数据模型包括视图和行为两部分,而Model层的数据模型只包含状态,比如:
页面的这一块展示什么,那一块展示什么,这些都是与试视图状态(展示)
试图家在进来时发生什么,点击这一块发生什么,这一块滚动时发生什么,这些都属于视图行为(交互)
视图行为和状态都封装在了ViewModel里,这样的封装使得ViewModel可以完整的去描述View层,由于实现了双向绑定,ViewModel层的数据会实时的展现在View层,这是激动人心的,因为前段开发者再也不必要去低效又麻烦的通过操作DOM取更新试图。
MVVM已经吧最脏最累的活儿干好了,开发者只需要处理和维护ViewModel,更新数据是图就会得到相应的更新,实现真正的事件驱动编程。
View层展现的不是Model层的数据,而是ViewModel的数据。
虚拟DOM
虚拟DOM的最终目标是将虚拟节点渲染到视图上。但是如果直接使用虚拟节点覆盖旧节点的话,会有很多不必要的DOM操作。例如,一个ul标签下很多个li标签,其中只有一个li有变化,这种情况下如果使用新的ul去替代旧的ul,因为这些不必要的DOM操作而造成了性能上的浪费。
为了避免不必要的DOM操作,虚拟DOM在虚拟节点映射到视图的过程中,将虚拟节点与上一次渲染视图所使用的旧虚拟节点(oldVnode)做对比,找出真正需要更新的节点来进行DOM操作,从而避免操作其他无需改动的DOM。
其实虚拟DOM在Vue.js主要做了两件事:
提供与真实DOM节点所对应的虚拟节点vnode
将虚拟节点vnode和旧虚拟节点oldVnode进行对比,然后更新视图
虚拟DOM是在内存里的
如何在console里调用vue组件属性
上面的文字终究是枯燥的,我们用实际操作来证明一下,为了更直观一些,我们需要在console里调用vue组件的属性。
通过 window.test = this 来定义一个全局变量,等于该组件的实例
<template>
<div class = "test">
<!--可以使用{{}}来绑定数据-->
<h1>{{msg}}</h1>
<!--也可以用v-bind来绑定,v-bind(绑定):title(你绑定到什么上,比如说我绑定到了title悬浮窗上)="mag(绑定到了什么上,我这里绑定到了data的msg上)"-->
<h2 v-bind:title="msg">你点点看</h2>
<!--class就是代表类的意思,当我们利用CSS样式的时候就可以指定类名为其指定样式,同名的样式相同-->
<span>HTMLspan元素是内联元素,可用作文本的容器</span>
</div>
</template>
<script>
export default {
name:"test",
data(){
return{
msg:'My Name Is ZhangSan'
}
},
created(){
//这行代码的意思是定义一个全局变量,等于该组件的实例
window.test = this
//这里请求的是我自己的springboot的接口的路径
this.$axios.post("api/crud/users").then(res=>{
console.log(res)
})
}
}
</script>
<style scoped>
h1, h2{
font-weight: normal;
}
</style>
绑定
我们进入页面之后是这样的
我们来见识一下绑定,现在我们看的还是单向绑定,View和Model
1、在console里通过 test.msg=“我是中国人” 修改test.msg的值
2、观察到绑定了msg的h1和h2的悬浮窗的值都已经发生了改变
基本语法
v-if 、v-else
我们新增一个h3和h4来验证if else,并在data中新增一个ok来存储一个布尔值
<template>
<div class = "test">
<!--可以使用{{}}来绑定数据-->
<h1>{{msg}}</h1>
<!--也可以用v-bind来绑定,v-bind(绑定):title(你绑定到什么上,比如说我绑定到了title悬浮窗上)="mag(绑定到了什么上,我这里绑定到了data的msg上)"-->
<h2 v-bind:title="msg">你点点看</h2>
<!--v-if 如果=后面的值为true,则展示-->
<h3 v-if="ok">Yes</h3>
<!--v-else 如果v-if的表达式不成立,则展示v-else里的内容-->
<h4 v-else>No</h4>
<!--class就是代表类的意思,当我们利用CSS样式的时候就可以指定类名为其指定样式,同名的样式相同-->
<span>HTMLspan元素是内联元素,可用作文本的容器</span>
</div>
</template>
<script>
export default {
name:"test",
data(){
return{
msg:'My Name Is ZhangSan',
ok: true
}
},
created(){
//这行代码的意思是定义一个全局变量,等于该组件的实例
window.test = this
//这里请求的是我自己的springboot的接口的路径
this.$axios.post("api/crud/users").then(res=>{
console.log(res)
})
}
}
</script>
<style scoped>
h1, h2{
font-weight: normal;
}
</style>
我们刚进入页面是这样的,只展示了h3,没有展示h4
我们再在console里修改ok的值,发现展示了h4,不再展示h3
v-if、v-if-else、v-else
<template>
<div class = "test">
<!--可以使用{{}}来绑定数据-->
<h1>{{msg}}</h1>
<!--也可以用v-bind来绑定,v-bind(绑定):title(你绑定到什么上,比如说我绑定到了title悬浮窗上)="mag(绑定到了什么上,我这里绑定到了data的msg上)"-->
<h2 v-bind:title="msg">你点点看</h2>
<!--v-if 如果=后面的值为true,则展示-->
<h3 v-if="ok">Yes</h3>
<!--v-else 如果v-if的表达式不成立,则展示v-else里的内容-->
<h4 v-else>No</h4>
<!--新增v-else-if,这里注意'A'是带''的-->
<h4 v-if="type==='A'">h5</h4>
<h4 v-else-if="type==='B'">h6</h4>
<h4 v-else-if="type==='C'">h7</h4>
<h4 v-else>h8</h4>
<!--class就是代表类的意思,当我们利用CSS样式的时候就可以指定类名为其指定样式,同名的样式相同-->
<span>HTMLspan元素是内联元素,可用作文本的容器</span>
</div>
</template>
<script>
export default {
name:"test",
data(){
return{
msg:'My Name Is ZhangSan',
ok: true,
type: 'V'
}
},
created(){
//这行代码的意思是定义一个全局变量,等于该组件的实例
window.test = this
//这里请求的是我自己的springboot的接口的路径
this.$axios.post("api/crud/users").then(res=>{
console.log(res)
})
}
}
</script>
<style scoped>
h1, h2{
font-weight: normal;
}
</style>
我们进来是这样的,展示h8
我们将type修改为A
for循环
<template>
<div class = "test">
<!--可以使用{{}}来绑定数据-->
<h1>{{msg}}</h1>
<!--也可以用v-bind来绑定,v-bind(绑定):title(你绑定到什么上,比如说我绑定到了title悬浮窗上)="mag(绑定到了什么上,我这里绑定到了data的msg上)"-->
<h2 v-bind:title="msg">你点点看</h2>
<!--v-if 如果=后面的值为true,则展示-->
<h3 v-if="ok">Yes</h3>
<!--v-else 如果v-if的表达式不成立,则展示v-else里的内容-->
<h4 v-else>No</h4>
<!--新增v-else-if,这里注意'A'是带''的-->
<h4 v-if="type==='A'">h5</h4>
<h4 v-else-if="type==='B'">h6</h4>
<h4 v-else-if="type==='C'">h7</h4>
<h4 v-else>h8</h4>
<!--class就是代表类的意思,当我们利用CSS样式的时候就可以指定类名为其指定样式,同名的样式相同-->
<span>HTMLspan元素是内联元素,可用作文本的容器</span>
<li v-for="name in namesss">{{name.namess}}</li>
</div>
</template>
<script>
export default {
name:"test",
data(){
return{
msg:'My Name Is ZhangSan',
ok: true,
type: 'V',
namesss:[
{namess: "张三"},
{namess:"李四"},
{namess:"王五"}
]
}
},
created(){
//这行代码的意思是定义一个全局变量,等于该组件的实例
window.test = this
//这里请求的是我自己的springboot的接口的路径
this.$axios.post("api/crud/users").then(res=>{
console.log(res)
})
}
}
</script>
<style scoped>
h1, h2{
font-weight: normal;
}
</style>
页面展示
如果你的Vscode有下面的报错
按照下图搜索“vetur.validation.template”,并取消选中(原来是被勾选状态),就没有报错了
定义方法
<template>
<div class = "test">
<!--可以使用{{}}来绑定数据-->
<h1>{{msg}}</h1>
<!--也可以用v-bind来绑定,v-bind(绑定):title(你绑定到什么上,比如说我绑定到了title悬浮窗上)="mag(绑定到了什么上,我这里绑定到了data的msg上)"-->
<h2 v-bind:title="msg">你点点看</h2>
<!--v-if 如果=后面的值为true,则展示-->
<h3 v-if="ok">Yes</h3>
<!--v-else 如果v-if的表达式不成立,则展示v-else里的内容-->
<h4 v-else>No</h4>
<!--新增v-else-if,这里注意'A'是带''的-->
<h4 v-if="type==='A'">h5</h4>
<h4 v-else-if="type==='B'">h6</h4>
<h4 v-else-if="type==='C'">h7</h4>
<h4 v-else>h8</h4>
<!--class就是代表类的意思,当我们利用CSS样式的时候就可以指定类名为其指定样式,同名的样式相同-->
<span>HTMLspan元素是内联元素,可用作文本的容器</span>
<li v-for="name in namesss">{{name.namess}}</li>
<!--新增一个button按钮,v-on指令用于绑定HTML事件, :click,绑定了一个click事件,="giantH",click后响应的函数-->
<el-button v-on:click="giantH">默认按钮</el-button>
</div>
</template>
<script>
export default {
name:"test",
data(){
return{
msg:'My Name Is ZhangSan',
ok: true,
type: 'V',
namesss:[
{namess: "张三"},
{namess:"李四"},
{namess:"王五"}
]
}
},
created(){
//这行代码的意思是定义一个全局变量,等于该组件的实例
window.test = this
//这里请求的是我自己的springboot的接口的路径
this.$axios.post("api/crud/users").then(res=>{
console.log(res)
})
},
//methods里面可以放很多方法,所以这里带一个s,而且他是一个对象,所以要用{}包裹起来
methods: {
//giant即为方法的名字,也有人说要写成function(event),但是我这里没写也没问题,不太清楚为什么
giantH: function(){
alert(this.msg);
}
}
}
</script>
<style scoped>
h1, h2{
font-weight: normal;
}
</style>
点击按钮后弹窗弹窗
双向绑定
上面我们看到的都是View绑定了Model,Model层变了之后通过VM层将变化展示在View层,现在我们要试一下View层数据变了,Model层也要跟着变,这就是双向绑定。
我们可以使用v-model指令在表单元素上创建双向绑定,且会忽略掉所有表单元素的value、checked、selected特性的初始值而总是将Vue实例的数据作为数据来源。
input
<template>
<div class = "test">
<!--可以使用{{}}来绑定数据-->
<h1>{{msg}}</h1>
<!--也可以用v-bind来绑定,v-bind(绑定):title(你绑定到什么上,比如说我绑定到了title悬浮窗上)="mag(绑定到了什么上,我这里绑定到了data的msg上)"-->
<h2 v-bind:title="msg">你点点看</h2>
<!--v-if 如果=后面的值为true,则展示-->
<h3 v-if="ok">Yes</h3>
<!--v-else 如果v-if的表达式不成立,则展示v-else里的内容-->
<h4 v-else>No</h4>
<!--新增v-else-if,这里注意'A'是带''的-->
<h4 v-if="type==='A'">h5</h4>
<h4 v-else-if="type==='B'">h6</h4>
<h4 v-else-if="type==='C'">h7</h4>
<h4 v-else>h8</h4>
<!--class就是代表类的意思,当我们利用CSS样式的时候就可以指定类名为其指定样式,同名的样式相同-->
<span>HTMLspan元素是内联元素,可用作文本的容器</span>
<li v-for="name in namesss">{{name.namess}}</li>
<!--新增一个button按钮,v-on指令用于绑定HTML事件, :click,绑定了一个click事件,="giantH",click后响应的函数-->
<el-button v-on:click="giantH">默认按钮</el-button>
<br>
<!--增加一个input输入框,通过v-model来绑定到msg上,再通过{{msg}}在输入框后面打印出对应msg的值-->
请输入信息: <input type="text" v-model="msg">{{msg}}
</div>
</template>
<script>
export default {
name:"test",
data(){
return{
msg:'My Name Is ZhangSan',
ok: true,
type: 'V',
namesss:[
{namess: "张三"},
{namess:"李四"},
{namess:"王五"}
]
}
},
created(){
//这行代码的意思是定义一个全局变量,等于该组件的实例
window.test = this
//这里请求的是我自己的springboot的接口的路径
this.$axios.post("api/crud/users").then(res=>{
console.log(res)
})
},
//methods里面可以放很多方法,所以这里带一个s,而且他是一个对象,所以要用{}包裹起来
methods: {
//giant即为方法的名字,也有人说要写成function(event),但是我这里没写也没问题,不太清楚为什么
giantH: function(){
alert(this.msg);
}
}
}
</script>
<style scoped>
h1, h2{
font-weight: normal;
}
</style>
进入页面是这样的
我们修改输入框中的值为nice
textarea和input是一样的
select
<template>
<div class = "test">
<!--可以使用{{}}来绑定数据-->
<h1>{{msg}}</h1>
<!--也可以用v-bind来绑定,v-bind(绑定):title(你绑定到什么上,比如说我绑定到了title悬浮窗上)="mag(绑定到了什么上,我这里绑定到了data的msg上)"-->
<h2 v-bind:title="msg">你点点看</h2>
<!--v-if 如果=后面的值为true,则展示-->
<h3 v-if="ok">Yes</h3>
<!--v-else 如果v-if的表达式不成立,则展示v-else里的内容-->
<h4 v-else>No</h4>
<!--新增v-else-if,这里注意'A'是带''的-->
<h4 v-if="type==='A'">h5</h4>
<h4 v-else-if="type==='B'">h6</h4>
<h4 v-else-if="type==='C'">h7</h4>
<h4 v-else>h8</h4>
<!--class就是代表类的意思,当我们利用CSS样式的时候就可以指定类名为其指定样式,同名的样式相同-->
<span>HTMLspan元素是内联元素,可用作文本的容器</span>
<li v-for="name in namesss">{{name.namess}}</li>
<!--新增一个button按钮,v-on指令用于绑定HTML事件, :click,绑定了一个click事件,="giantH",click后响应的函数-->
<el-button v-on:click="giantH">默认按钮</el-button>
<br>
<!--增加一个input输入框,通过v-model来绑定到msg上,再通过{{msg}}在输入框后面打印出对应msg的值-->
请输入信息: <input type="text" v-model="msg">{{msg}}
<br>
<!--新增一个下拉框,在select标签上绑定了selected的值,一个请选择,是点开下拉框后被置为disable的那个文案,第二个请选择是没点开下拉框的时候在外面展示的文案-->
下拉框:
<select v-model = "selected">
<option value="请选择" disabled>请选择</option>
<option>A</option>
<option>B</option>
<option>C</option>
</select>
<span>选择了: {{selected}}</span>
</div>
</template>
<script>
export default {
name:"test",
data(){
return{
msg:'My Name Is ZhangSan',
ok: true,
type: 'V',
namesss:[
{namess: "张三"},
{namess:"李四"},
{namess:"王五"}
],
selected: '请选择'
}
},
created(){
//这行代码的意思是定义一个全局变量,等于该组件的实例
window.test = this
//这里请求的是我自己的springboot的接口的路径
this.$axios.post("api/crud/users").then(res=>{
console.log(res)
})
},
//methods里面可以放很多方法,所以这里带一个s,而且他是一个对象,所以要用{}包裹起来
methods: {
//giant即为方法的名字,也有人说要写成function(event),但是我这里没写也没问题,不太清楚为什么
giantH: function(){
alert(this.msg);
}
}
}
</script>
<style scoped>
h1, h2{
font-weight: normal;
}
</style>
进入页面是这样的
选择下拉框