Vue基本指令 (上)

简介: Vue基本指令 (上)

一. v-on指令



1. 基础用法


v-on是事件监听的指令, 下面来看简单用法

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div id="app">
    <h2>{{counter}}</h2>
    <button v-on:click="add"> + </button>
    <button v-on:click="sub"> - </button>
</div>
<script src="../js/vue.js"></script>
<script>
    var app = new Vue({
        el: "#app",
        data: {
            counter: 0
        },
        methods: {
            add() {
                this.counter ++
            },
            sub() {
                this.counter --
            }
        }
    });
</script>
</body>
</html>

我们给按钮绑定了点击事件. v-on:click = "add"

  • v-on: 后面加时间名称
  • 需要指定绑定事件的事件名

来看看运行效果


1187916-20210220155403887-2072037544.gif

2. 语法糖

我们知道, v-bind指令可以简写为:, 同样v-on也可以简写, 简写为@, 如上写法可以简写如下:

<button @click="add"> + </button>
<button @click="sub"> - </button>

3. 事件的参数


  • 无参方法


上面的案例都是不带参数. 如果方法没有参数, 那么我们在调用的时候可以省略括号

add方法不带参数, 调用的时候可以有如下两种写法:
<button @click="add"> + </button>
或者
<button @click="add()"> + </button>

两种写法都可.


  • 有参方法


如果一个方法有参数, 如下案例

<script>
    var app = new Vue({
        el: "#app",
        data: {
            num1: 10,
            num2: 100
        },
        methods: {
            print(message) {
                console.log("打印" + message)
            }
        }
    });
</script>

调用方式1: 那么调用的时候括号里不带参数.

<div id="app">
    <button @click="print()"> 打印 </button>
</div>

这是方法的参数传入的是undefined.

1187916-20210220161301678-1514074101.png

调用方式2: 不带括号

<div id="app">
    <button @click="print"> 打印 </button>
</div>

这里和方式1的区别是, 调用方法的括号都省了.

这时会是什么效果呢?

1187916-20210220161512215-1926474621.png


可以看到, 这时不是undefined了, 而是一个MouseEvent鼠标事件.


为什么呢? 其实, 当鼠标点击按钮的时候, 页面会自动生成一个事件, 如果没有传递参数, 那么会自动将这个事件作为参数传递过了, 如果需要调用这个事件, 那么, 可以在方法入参,显示的接收event参数.

 

调用方式3: 参数中既有普通参数, 又有event参数


这是我们调用的时候, 要使用$event

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div id="app">
    <button @click="print"> button1 </button>
    <button @click="print1('aaa')"> button2 </button>
    <button @click="print1('aaa', $event)"> button3 </button>
</div>
<script src="../js/vue.js"></script>
<script>
    var app = new Vue({
        el: "#app",
        data: {
            num1: 10,
            num2: 100
        },
        methods: {
            print(message) {
                console.log("打印" + message)
            },
            print1(message, event){
                console.log("打印" + event + ", message:" + message)
            },
            print2(message, event) {
                console.log("event:" + event + ", message:" + message)
            }
        }
    });
</script>
</body>
</html>

然后来看效果

1187916-20210220163050410-746040793.png


同时将message和event都传递过来了


4. 事件修饰符


  • .stop : 调用event.stopPropagation() 阻止冒泡事件

看如下代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div id="app" @click="divClick">
    <button @click="btnClick">按钮</button>
</div>
<script src="../js/vue.js"></script>
<script>
    var app = new Vue({
        el: "#app",
        data: {
            message: "hello"
        },
        methods:{
            divClick(){
                console.log("divClick")
            },
            btnClick(){
                console.log("btnClick")
            }
        }
    });
</script>
</body>
</html>

div里面有一个btn, div有一个click事件, btn也有一个click事件, 当我们点击btn的时候, 回调用两个方法么?我们来看看效果


1187916-20210220164118300-1088575746.png

确实调用了btn的click()方法, 而且还调用了div的click()方法. 这是事件冒泡机制, 通常我们在页面是要避免这样的情况发生的. 所以会写一个方法阻止事件冒泡.


但是在vue里面, 使用stop修饰符就可以解决这个问题. 在btn按钮的click事件上增加stop修饰符

<div id="app" @click="divClick">
    <button @click.stop="btnClick">按钮</button>
</div>

这样就阻止了冒泡事件

1187916-20210220164419565-1982461090.png

  • .prevent: 调用event.preventDefault() 阻止默认事件

我们现在methods中定义一个方法

stopDefaultEventBtn(){
    console.log("stopDefaultEventBtn")
}          

调用的时候, 我们定义一个submit表单提交按钮, 我们知道表单有自己的提价时间, 点击按钮将跳转到form表单指定的action地址.

<div id="app" @click="divClick">
    <button @click.stop="btnClick">阻止冒泡事件</button><br/><br/>
    <form action="http://www.baidu.com">
        <input type = "submit" value="阻止默认事件"></input>
    </form>
</div>

现在我们不想使用submit的自动提交事件, 我们要阻止他, 而是使用我么自定义的stopDefaultEventBtn事件.

<div id="app" @click="divClick">
    <button @click.stop="btnClick">阻止冒泡事件</button><br/><br/>
    <form action="http://www.baidu.com">
        <input type = "submit" @click.prevent="stopDefaultEventBtn" value="阻止默认事件"></input>
    </form>
    <!-- submit 有自己的模式提交事件, 但通常我们不希望使用默认的提交时间, 而是使用我自定义的事件. -->
</div>

这时, 我们在调用方法, 发现不会自动跳转到action指定的事件了, 而是进入到click事件.


image.gif

但是有个问题, 虽然调用了click指定的事件, 但是依然有事件冒泡, 同时还调用和div的click事件, 这个简单, 在增加阻止冒泡事件就可以了.

<div id="app" @click="divClick">
    <button @click.stop="btnClick">阻止冒泡事件</button><br/><br/>
    <form action="http://www.baidu.com">
        <input type = "submit" @click.prevent.stop="stopDefaultEventBtn" value="阻止默认事件"></input>
    </form>
    <!-- submit 有自己的模式提交事件, 但通常我们不希望使用默认的提交时间, 而是使用我自定义的事件. -->
</div>
  • .(keyCode | keyAlias): 只当事件是从特定键触发时才触发回调

我们来监听一个键盘的按键事件 --- 监听键盘上回车按钮的按键事件


<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div id="app">
    <input type="text" @keyup.enter="keyup" /><br/><br/>
</div>
<script src="../js/vue.js"></script>
<script>
    var app = new Vue({
        el: "#app",
        data: {
            message: "hello"
        },
        methods:{
            keyup() {
                console.log("keyup")
            }
        }
    });
</script>
</body>
</html>

@keyup.enter="keyup" 在keyup事件后面增加.enter即可


  • .once: 只触发一次回调


增加了 .once的事件, 只有第一次点击有反应, 后面点击就没有反应了.


二. v-if指令


条件判断, 有三个指令


  • v-if
  • v-else-if
  • v-else


来看案例

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<!-- 我们开发过程中通常会遇到状态, 1:表示启用, 2:表示禁用 3: 表示删除-->
<div id="app">
    <h2 v-if = "status == 1"> 启用 </h2>
    <h2 v-else-if = "status == 2"> 禁用 </h2>
    <h2 v-else> 删除 </h2>
</div>
<script src="../js/vue.js"></script>
<script>
    var app = new Vue({
        el: "#app",
        data: {
            status: 1
        }
    });
</script>
</body>
</html>

这个案例很简单,就不说了. 有一点可以说, 就是通常只有两种情况, 很简单的两种情况,我们会使用v-if, v-else. 如果情况很复杂, 不建议在代码写很多v-else-if, 因为可读性差, 我们应该吧条件判断放到methods或者computed中进行计算, 最后返回结果.

 

案例: 登录界面使用账号登录和邮箱登录的切换


<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<!-- 我们开发过程中通常会遇到状态, 1:表示启用, 2:表示禁用 3: 表示删除-->
<div id="app">
    <label v-if="userLogin">账号登录
    <input type="text" placeholder="请输入账号">
    </label>
    <label v-else>邮箱登录
        <input type="text" placeholder="请输入邮箱">
    </label>
    <button @click="userLogin = !userLogin" >切换</button>
</div>
<script src="../js/vue.js"></script>
<script>
    var app = new Vue({
        el: "#app",
        data: {
            userLogin: true
        }
    });
</script>
</body>
</html>


在这里, 我们定义了一个变量userLogin, 是否是用户登录, 默认是true; 定义两个label和一个button, 点击切换按钮, 来两个label之间来回切换.效果如下图

1187916-20210220180000115-700461589.gif


但是这里有个问题, 当我们输入内容以后, 切换文本框的时候, 内容却不会消失. 如下图

1187916-20210220180123731-1962078976.gif

  • 存在的问题: 切换了类型, 输入的文字却没有被清空.


    我们发现, 在账号登录里面输入了1234, 切换到邮箱登录的时候, 却没有被清空. 这是两个文本框, 但是值怎么被带过来了呢?


  • 原因


这是由于vue在进行dom渲染时, 考虑到性能问题, 会尽可能复用已经存在的元素. 而不是每次都创建新的元素. 这就是vue的虚拟dom.

1187916-20210220181929872-1971906336.png


如上图, 我们的dom元素, 之前都是直接渲染到浏览器页面的. 但是增加了vue以后, vue会帮我们将dom元素先进行缓存, 缓存为虚拟dom.


当我们使用v-if指令的时候, 两个div的元素不可能同时执行. 第一个div元素被渲染了以后, 在渲染第二个div的时候, 他发现有类似的元素, 那么vue就缓存一份. 当执行到else的时候, vue判断元素一样, 只是部分内容不同, 那就渲染不同的部分,相同的不会修改. 而我们输入的内容, 不在比较的范围内, 所以, 会被带过去.

 

  • 如何避免这种情况呢? 使用属性key


<div id="app">
    <label v-if="userLogin">账号登录
    <input type="text" placeholder="请输入账号" key="user">
    </label>
    <label v-else>邮箱登录
        <input type="text" placeholder="请输入邮箱" key="email">
    </label>
    <button @click="userLogin = !userLogin" >切换</button>
</div>


如果两个key是一样的, 那么就虚拟dom就缓存一份, 如果两个key是不同的, 那么虚拟dom就会缓存两份. 来看看这次的效果


1187916-20210220182703325-179191368.gif


相关文章
|
2月前
|
JavaScript
Vue中如何实现兄弟组件之间的通信
在Vue中,兄弟组件可通过父组件中转、事件总线、Vuex/Pinia或provide/inject实现通信。小型项目推荐父组件中转或事件总线,大型项目建议使用Pinia等状态管理工具,确保数据流清晰可控,避免内存泄漏。
281 2
|
26天前
|
缓存 JavaScript
vue中的keep-alive问题(2)
vue中的keep-alive问题(2)
256 137
|
5月前
|
人工智能 JavaScript 算法
Vue 中 key 属性的深入解析:改变 key 导致组件销毁与重建
Vue 中 key 属性的深入解析:改变 key 导致组件销毁与重建
720 0
|
5月前
|
JavaScript UED
用组件懒加载优化Vue应用性能
用组件懒加载优化Vue应用性能
|
4月前
|
人工智能 JSON JavaScript
VTJ.PRO 首发 MasterGo 设计智能识别引擎,秒级生成 Vue 代码
VTJ.PRO发布「AI MasterGo设计稿识别引擎」,成为全球首个支持解析MasterGo原生JSON文件并自动生成Vue组件的AI工具。通过双引擎架构,实现设计到代码全流程自动化,效率提升300%,助力企业降本增效,引领“设计即生产”新时代。
384 1
|
4月前
|
JavaScript 安全
在 Vue 中,如何在回调函数中正确使用 this?
在 Vue 中,如何在回调函数中正确使用 this?
223 0
|
5月前
|
JavaScript 前端开发 开发者
Vue 自定义进度条组件封装及使用方法详解
这是一篇关于自定义进度条组件的使用指南和开发文档。文章详细介绍了如何在Vue项目中引入、注册并使用该组件,包括基础与高级示例。组件支持分段配置(如颜色、文本)、动画效果及超出进度提示等功能。同时提供了完整的代码实现,支持全局注册,并提出了优化建议,如主题支持、响应式设计等,帮助开发者更灵活地集成和定制进度条组件。资源链接已提供,适合前端开发者参考学习。
450 17
|
5月前
|
JavaScript 前端开发 UED
Vue 表情包输入组件实现代码及详细开发流程解析
这是一篇关于 Vue 表情包输入组件的使用方法与封装指南的文章。通过安装依赖、全局注册和局部使用,可以快速集成表情包功能到 Vue 项目中。文章还详细介绍了组件的封装实现、高级配置(如自定义表情列表、主题定制、动画效果和懒加载)以及完整集成示例。开发者可根据需求扩展功能,例如 GIF 搜索或自定义表情上传,提升用户体验。资源链接提供进一步学习材料。
264 1
|
5月前
|
存储 JavaScript 前端开发
如何高效实现 vue 文件批量下载及相关操作技巧
在Vue项目中,实现文件批量下载是常见需求。例如文档管理系统或图片库应用中,用户可能需要一次性下载多个文件。本文介绍了三种技术方案:1) 使用`file-saver`和`jszip`插件在前端打包文件为ZIP并下载;2) 借助后端接口完成文件压缩与传输;3) 使用`StreamSaver`解决大文件下载问题。同时,通过在线教育平台的实例详细说明了前后端的具体实现步骤,帮助开发者根据项目需求选择合适方案。
470 0
|
5月前
|
JavaScript 前端开发 UED
Vue 项目中如何自定义实用的进度条组件
本文介绍了如何使用Vue.js创建一个灵活多样的自定义进度条组件。该组件可接受进度段数据数组作为输入,动态渲染进度段,支持动画效果和内容展示。当进度超出总长时,超出部分将以红色填充。文章详细描述了组件的设计目标、实现步骤(包括props定义、宽度计算、模板渲染、动画处理及超出部分的显示),并提供了使用示例。通过此组件,开发者可根据项目需求灵活展示进度情况,优化用户体验。资源地址:[https://pan.quark.cn/s/35324205c62b](https://pan.quark.cn/s/35324205c62b)。
212 0