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


相关文章
|
1天前
|
JavaScript
Vue实战-组件通信
Vue实战-组件通信
4 0
|
1天前
|
JavaScript
Vue实战-将通用组件注册为全局组件
Vue实战-将通用组件注册为全局组件
5 0
|
1天前
|
JavaScript 前端开发
vue的论坛管理模块-文章评论02
vue的论坛管理模块-文章评论02
|
1天前
|
JavaScript Java
vue的论坛管理模块-文章查看-01
vue的论坛管理模块-文章查看-01
|
1天前
|
JavaScript
vue页面加载时同时请求两个接口
vue页面加载时同时请求两个接口
|
1天前
|
JavaScript
vue里样式不起作用的方法,可以通过deep穿透的方式
vue里样式不起作用的方法,可以通过deep穿透的方式
|
1天前
|
移动开发 JavaScript 应用服务中间件
vue打包部署问题
Vue项目`vue.config.js`中,`publicPath`设定为&quot;/h5/party/pc/&quot;,在线环境基于打包后的`dist`目录,而非Linux的`/root`。Nginx代理配置位于`/usr/local/nginx/nginx-1.13.7/conf`,包含两个相关配置图。
vue打包部署问题
|
1天前
|
JavaScript 前端开发
iconfont 图标在vue里的使用
iconfont 图标在vue里的使用
11 0
|
1天前
|
资源调度 JavaScript 前端开发
vue 项目运行过程中出现错误的问题解决
vue 项目运行过程中出现错误的问题解决
|
1天前
|
JavaScript 前端开发
VUE里父组件与子组件的交互操作
VUE里父组件与子组件的交互操作