一 MVVM模型
在讲vue之前,我们需要先熟悉一种软件设计架构模式。
介绍完了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:名字=“变量” 简写: #名字=“变量”
本阶段总结暂时就到这啦,加油!