目录
一 MVVM模型
在讲vue之前,我们需要先熟悉一种软件设计架构模式。
什么是mvvm模型?翻译过来就是Model-View-ViewModel。它将我们的应用程序分为三个部分:
在讲之前我们先想象一下,我们平时使用app,我们看见的是不是app的页面展示出来的,页面上面有各种图片,文字等数据。所以我们能看见的app主要分为两个部分,一个是app的页面,另外一个就是页面渲染的数据,那么现在就很好解释MVVM模型了。
①View:这就是我们平时在app看见的页面,而页面则是各种各样的DOM元素组成的,比如标题,按钮,div盒子等等,所以View就是这些DOM元素。
②Model:既然有了页面,那么不难理解,这就是页面渲染的各式各样的数据,所以Model就是数据,不过它是完全独立的。
③ViewModel:既然页面和数据都有了,那么这个又是干嘛的呢?刚刚我们可以看见,Model是完全独立的,那么问题就来了,我该怎么把数据渲染到对应的页面上去呢?没错,这就ViewModel的作用,它是View和Model之间的桥梁,负责将 Model 的数据转换为 View 可以展示的格式,并处理用户与 View 的交互。
介绍完了MVVM模型三部分,那么我们接下来图文并茂,通过图片再具体的理解:
MVVM模型在代码中的具体展示:
二 v-bind 和 v-model 指令
本次把它们两个指令放在一起讲,主要是用于区分它们两个指定,其实它们区别很大,本来也就是不同的应用场景,但是因为它们都是绑定变量来动态生成变量值的,所以还是选择一起来讲。
1.v-bind
一句话概括:就是用来动态绑定标签的属性值的。
格式:v-bind:属性名=“变量名” , 简写成 : :属性名=“变量名”
这里有几个关键字:
标签属性值:就是每个标签都有它的属性,比如<img>标签有src属性,<a>标签有href属性。
动态绑定:就是这些属性值不像以前一样写死,而是用一个变量来代取,从而动态生成。
到这里v-bind已经介绍完了,就是用来动态绑定标签属性的数据的。下面用演示代码再来展示一下:
① 这里<img>标签中有一个src属性,如果我们不用v-bind,那么src里面的图片路径只能是写死的。但是我们使用了v-bind就不一样了,里面的imgUrl并不是一个常量图片路径,而是一个变量,它的值根据你返回的数据来决定。这样我们就可以实现图片的动态切换。
<img :src="imgUrl" alt="" style="width: 100px; height: 100px;"> <button @click="change">切换图片</button>
② 同样,style也是大多数标签的一个属性,所以只要是标签的属性,v-bind也可以动态绑定
<!-- 同样,style也是大多数标签的一个属性,所以只要是标签的属性,v-bind也可以动态绑定 --> <h2 :style="{color:fontColor , 'font-size':fontSize+'px'}">我是字体</h2> <button @click="changeSize">改变字体样式</button>
最终实现了页面的动态控制:
2.v-model
它是用于数据的双向绑定,并且主要用于表单输入。
格式:v-model="输入表单内容变量名"
其实从书写格式我们就能看出来它和v-bind的区别:
v-model=“变量名”
v-bind :属性名=“变量名”
所以它们的应用场景就已经确定了它们两个的区别。
v-bind用于标签属性的绑定,v-model用于表单内容的绑定。
代码展示:
<input type="text" placeholder="请输入用户名" v-model="username" value="默认值"/> <h2>{{username}}</h2>
所以v-model实现了表单数据的双向绑定,无论是页面输入的内容还是数据发生改变,对应的对方也会改变。
1.文本类型的
<input>
和<textarea>
元素会绑定value
property 并侦听input
事件; v-model会覆盖元素的value属性
2.<input type="checkbox">
和<input type="radio">
会绑定checked
property 并侦听change
事件;
3.<select>
会绑定value
property 并侦听change
事件。
三 v-if 和 v-show 指令
这里不详细介绍用法,因为大致相同,主要在于介绍它们两个指令的区别。
格式: v-if = “boolean值” (true: 对应标签就会渲染, false: 不渲染 )
v-show的作用也是一样。
1.v-if 和 v-show 的区别
v-if: 切换显示与隐藏, 通过是否渲染标签, 对标签添加与删除
如果频繁的显示与隐藏切换: 不推荐使用v-if; 性能低
v-show:控制标签显示隐藏, 控制标签display样式属性,从而控制标签显示与隐藏。
四 计算属性和侦听器
其实都是用来监听对象是否发生变化,一旦发生变化就会调用对应的函数,执行相关逻辑,最后返回一个新的数据。
但是它们区别也很大。
1.区别
① 计算属性是所依赖的数据发生变化时调用函数。
什么叫做所依赖的数据,就是你函数里面用到的数据,比如你要用num1+num2求和,那么num1和num2就是你所依赖的数据,当它们发生变化就会执行计算属性函数中的get方法。
侦听器是你指定的数据或对象发生变化时,调用函数。
② 计算属性不支持异步操作,所以不能在计算属性函数中发送ajax请求。而侦听器支持异步操作。
③ 计算属性需要调用sum并且get方法中需要return值来映射到{{sum}}中。
侦听器不需要返回值,因为它是对data中的数据进行监听,也就是说,它侧重的是对数据的监听和修改。
2.代码
计算属性:
<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>计算属性</title> <style> input{ width:50px; } </style> </head> <body> <div id="app"> <input type="number" v-model="num1" /> + <input type="number" v-model="num2" /> = <!-- 调用sum方法 --> {{sum}} <hr/> <!-- 调用sum方法 --> {{sum}} </div> <script type="text/javascript" src="./js/vue.global.js"></script> <script> // 1.创建app const app = Vue.createApp({ // data: option api data: function() { return { num1:0, num2:0 } }, methods:{ // sum(){ // console.log("sum..."); // return parseInt(this.num1) + parseInt(this.num2); // } }, computed:{ //计算属性 sum:{ get(){ console.log("sum..."); return this.num1 + this.num2; } } } }) // 2.挂载app app.mount("#app") </script> </body> </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>监听属性</title> <style> input{ width:50px; } </style> </head> <body> <div id="app"> <input type="number" v-model="num1" /> + <input type="number" v-model="num2" /> = <!-- {{sum()}} --> {{sum}} <hr/> <!-- {{sum()}} --> {{sum}} </div> <script type="text/javascript" src="./js/vue.global.js"></script> <script> // 1.创建app const app = Vue.createApp({ // data: option api data: function() { return { num1:0, num2:0, sum:0 } }, watch:{ num1(newVal,oldVal){ //console.log(newVal); //console.log(oldVal); this.sum = newVal + this.num2; }, num2(newVal,oldVal){ this.sum = newVal + this.num1; }, } }) // 2.挂载app app.mount("#app") </script> </body> </html>
五 组件通信
什么是组件通信? 我们一般开发网页是按照分模块开发的,最后在整合在一起。
假如现在有两个页面a和b,此时如果a页面导入了b页面,那么a页面就叫做父页面,b页面就是a页面的子页面。那么如果a,b两个页面需要进行数据的传输,那么就叫做两个组件之间的通信。
1.父传子
把父组件的数据传递给子组件显示.
实现方式:
① 子组件实例使用props定义可接受数据的属性
② 在父组件中, 使用子组件标签, 给定义属性赋值
注意:
给子组件传递的数据写死在子组件标签上, 静态的值
如果给子组件传递数据通过请求后台得到数据, 动态的值
props对象写法:
props:{
属性名:{
type: 数据类型,
required: boolean类型: true必须 false可选,
default: 值/函数 默认值
validator: 函数 数据校验
},
....
}
2.子传父
跟父传子不同,子传父并不是直接传送数据,而是子组件中发生了点击,父组件需要对应实现内容的切换。这个时候需要用到子传父。
① 当子组件点击按钮调用函数,使用$emil()自定义事件。(也可以传参数后面跟逗号加参数)
② 父组件在对应导入的子组件标签中绑定这个自定义事件。
最后在父组件定义对应的incr和decr函数,然后实现父组件的内容切换的逻辑。
六 插槽
插槽本质上也是子组件和父组件之间的一种联系。它和组件通信不同,它不是单纯的父子组件之间的数据通信,虽然它也有,不过主要是父组件写好的模块插入到子组件中。
所以接下来我也主要就父组件对子组件插入模块和子组件对父组件传输数据这两部分来讲。
插槽: 让父组件给子组件传递模版(dom标签)
① 在子组件定义一个插槽(<slot> </slot>)
② 在父组件引入子组件,并在子组件标签中插入模板
这样父组件的模板就成功插入到子组件<Helloword>中显示了。
1.默认插槽
使用默认名: default, 一个组件只能有一个默认插槽 。
父组件接收默认插槽
最外面是子组件标签名,然后里面使用<template>标签,使用#default表示默认插槽
2.具名插槽
在子组件中<slot>使用name属性指定一个名字
在父组件给子组件指定插槽传递模版
使用
<template>
给指定插槽传递模版, 在template标签中使用v-slot
指定插槽名v-slot:名字
3.传输数据
插槽还可以进行数据传输,不过它只能子组件给父组件传输。
可能会问,刚刚不是用组件通信也能完成子组件向父组件传输数据,这两个有什么区别?
有。组件通信,子组件向父组件传输数据主要是因为子组件触发事件影响到父组件,也就是前提是需要子组件触发条件。而这个不需要,只需要子组件的插槽把数据带回父组件,父组件直接获取对应的插槽就可以得到数据了。
①默认插槽向父组件传输数据:
可以看出来这是用了v-bind绑定数据。
②在父组件使用使用v-slot=“变量名”接收数据
具名插槽向父组件传输数据:
① 子组件没有变化,当然,记得给子组件取名。
②父组件获取数据: v-slot:名字=“变量” 简写: #名字=“变量”
本阶段总结暂时就到这啦,加油!