class 2: vue.js 3 模板语法和内置指令

插值语法

  • 多数情况下,Vue.js 3使用HTML模板(template)语法,通过声明式将组件开发实例的数据与DOM绑定在一起。模板语法的核心是插值(mustache)语法和指令。在Vue.js 3中,要将数据显示到模板中,常见的方式是使用插值语法,也称双大括号语法
  • 下面的代码演示了插值语法的具体应用
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <div id="app"></div>
    <template id="my-app">
        <h4> {{ message }} - {{ isShow }}</h4>
        <h4> {{ counter * 100 }}</h4>
        <h4> {{ message.split(" ").join(",")}}</h4>
        <h4> {{ getReverseMessage() }} </h4>
        <h4> {{ isShow ? "三元运算符": ""}}</h4>
        <button @click="toggle">切换控制显示</button>
    </template>
    <script src="./js/vue.js"></script>
    <script>
        const App = {
            template: '#my-app',
            data() {
                return {
                    message: 'Hello World',
                    counter: 100,
                    isShow: true,
                }
            },
            methods: {
                getReverseMessage() {
                    return this.message.split(" ").reverse().join(" ")
                },
                toggle() {
                    this.isShow = !this.isShow
                }
            }
        }
        Vue.createApp(App).mount('#app')
    </script>
</body>
</html>
  • 效果如下
    在这里插入图片描述

  • 上述例子说明插值语法支持绑定data中的属性、还支持javascript表达式、调用方法、三元运算符等

基本指令

  • template中,我们会经常看到以v-开头的属性(attribute),它们被称为指令,通常,指令带有前缀v-,意味着这是Vue.js 3提供的特殊属性。它们会在渲染的DOM上应用特殊的响应式行为。下面介绍几种常见的指令

v-once

  • v-once指令用于指定元素或组件只渲染一次。当数据发生变化时,元素或组件及其所有的子组件将被视为静态内容,跳过更新。通常在需要进行性能优化时使用v-once指令
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <div id="app"></div>
    <template id="my-app">
        <h2>h2 : {{ counter }}</h2>
<!--        下面的内容只会被渲染一次-->
        <h3 v-once>h3 : {{ counter }}</h3>
        <div v-once>
            <h4>h4 : {{ counter }}</h4>
            <h5>h5 : {{ message }}</h5>
        </div>
<!--        点击触发重新渲染-->
        <button @click="increment">+1</button>
    </template>
    <script src="./js/vue.js"></script>
    <script>
        const App = {
            template: "#my-app",
            data() {
                return {
                    counter: 100,
                    message: "Hello World!"
                }
            },
            methods: {
                increment() {
                    this.counter += 1
                }
            }
        }
        Vue.createApp(App).mount("#app")
    </script>
</body>
</html>
  • 效果如下,只有<h2>标签的元素会被重新渲染,其他的都只渲染一次
    在这里插入图片描述

v-text

  • v-text指令用于更新元素的textContent,也就是说,实际上v-text指令就相当于插值语法
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <div id="app"></div>
    <template id="my-app">
<!--        这两种用法效果一样-->
        <h2 v-text="message"></h2>
        <h2> {{ message }}</h2>
    </template>
</body>
<script src="./js/vue.js"></script>
<script>
    const App = {
        template: '#my-app',
        data() {
            return {
                message: "Hello World"
            }
        }
    }
    Vue.createApp(App).mount('#app')
</script>
</html>

在这里插入图片描述

v-html

  • 当展示的内容是HTML字符串时,Vue.js 3不会对其进行特殊的解析。如果希望HTML字符串的内容可以被Vue.js 3解析出来,那么可以使用v-html指令,如下所示
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <div id="app"></div>
    <template id="my-app">
<!--        这段代码会将message对应的HTML代码解析出来-->
        <h2 v-html="message"></h2>
        <h2> {{ message }}</h2>
    </template>
    <script src="./js/vue.js"></script>
    <script>
        const App = {
            template: '#my-app',
            data() {
                return {
                    message: '<span style="color: red; background: blue"> Hello Vue.js 3</span>'
                }
            }
        }
        Vue.createApp(App).mount('#app')
    </script>
</body>
</html>

v-pre

  • v-pre指令用于跳过元素及其子元素的编译过程,从而加快编译速度,如下所示
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <div id="app"></div>
    <template id="my-app">
        <h2 v-pre> {{ message }}</h2>
    </template>
<script src="./js/vue.js"></script>
<script>
    const App = {
        template: '#my-app',
        data() {
            return {
                message: "Hello World"
            }
        }
    }
    Vue.createApp(App).mount('#app')
</script>
</body>
</html>
  • 上面的代码会原样显示{{ message }},而不会显示message的值,因为绑定v-pre指令后的<h2>元素和它的子元素将会跳过编译过程

v-cloak

  • v-cloak指令需要隐藏未编译的mustache标签,直到组件实例完成编译。它需要和CSS规则一起使用,例如[v-cloak] { display: none}
  • 在Vue.js 3中,这个指令的使用频率不高。因为生产阶段的模板已提前编译完成,所以不需要使用v-cloak指令

v-bind

1. 绑定基本属性

  • 上面的指令用于为元素绑定内容,元素除了绑定内容之外,还需要绑定各种各样的属性。此时,可以使用v-bind指令来绑定这些属性
  • 很多时候,元素的属性是动态的,比如<a>元素的href属性、<img>元素的src属性等。通常需要动态插入值,这时可以使用v-bind指令来绑定这些属性
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <div id="app"></div>
    <template id="my-app">
        <img v-bind:src="imgUrl" alt="">
        <a v-bind:href="link">百度一下</a>
        <img :src="imgUrl" alt="" sty>
        <img src="imgUrl" alt="">
    </template>
    <script src="./js/vue.js"></script>
    <script>
        const app = {
            template: '#my-app',
            data() {
                return {
                    imgUrl: "https://v2.cn.vuejs.org/images/logo.svg",
                    link: "https://www.baidu.com"
                }
            }
        }
        Vue.createApp(app).mount('#app')
    </script>
</body>
</html>
  • :是v-bind指令的简写,:src=“imgUrl”的意思就是把imgUrl变量绑定到src属性上

2. 绑定class属性

  • v-bind可以用于绑定元素或者组件的class属性,支持绑定的类型有字符串、对象和数组类型。代码示例如下
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div id="app"></div>
<template id="my-app">
    <div :class="'abc'">class绑定字符串1</div>
    <div :class="className">class绑定字符串2</div>
    <div :class="{'active': isActive}">class绑定对象1</div>
    <div :class="{active: isActive, title: true}">class绑定对象2</div>
    <div class="abc cba" :class="{active: isActive, title: true}">默认class和动态class结合</div>
    <div class="abc cba" :class="classObj">绑定属性中的对象</div>
    <div class="abc cba" :class="getClassObj()">绑定methods/computed返回的对象</div>
    <button @click="toggle()">切换isActive</button>
</template>
<script src="./js/vue.js"></script>
<script>
    const app = {
        template: '#my-app',
        data() {
            return {
                className: "hello world",
                isActive: true,
                classObj: {
                    active: true,
                    title: true
                }
            }
        },
        methods: {
            toggle() {
                this.isActive = !this.isActive
            },
            getClassObj() {
                return {
                    active: false,
                    title: true
                }
            }
        }
    }
    Vue.createApp(app).mount('#app')
</script>
</body>
</html>
  • 此外v-bind还可绑定其他类型。具体可以参考其他资料

v-on

  • 交互是前端开发非常重要的一部分,,例如处理单击、拖拽、键盘事件等。在Vue.js 3中,使用v-on指令可以实现对这些事件的监听,这个指令简写为@

1. 绑定事件

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div id="app"></div>
<template id="my-app">
    <button v-on:click="btn1Click">监听按钮单击(完整写法)</button>
    <div class="area" v-on:mousemove="mouseMove">监听鼠标移动事件</div>
<!--    @是v-on的语法糖-->
    <button @click="btn1Click">监听按钮点击(简写)</button>
    <button @click="counter++">单击+1: {{ counter }}</button>
    <div class="area" v-on="{click: btn1Click, mousemove: mouseMove}">监听鼠标移动事件</div>
    <div class="area" @="{click: btn1Click, mousemove: mouseMove}">监听鼠标移动事件(简写)</div>
</template>
<script src="./js/vue.js"></script>
<script>
    const app = {
        template: '#my-app',
        data() {
            return {
                message: 'Hello World',
                counter: 100
            }
        },
        methods: {
            btn1Click() {
                console.log('按钮1发生了单击')
            },
            mouseMove() {
                console.log('鼠标移动')
            }
        }
    }
    Vue.createApp(app).mount('#app')
</script>
</body>
</html>

2. 事件对象和传递参数

  • 事件在发生时会产生事件对象,我们可以在事件回调函数中获取事件对象,还是用上面的例子,但是btn2Click加了个name参数,$event是固定写法,专门用于获取事件对象
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div id="app"></div>
<template id="my-app">
    <button v-on:click="btn1Click">监听按钮单击(完整写法)</button>
    <div class="area" v-on:mousemove="mouseMove">监听鼠标移动事件</div>
<!--    @是v-on的语法糖-->
    <button @click="btn2Click($event, 'hello')">监听按钮点击(简写)</button>
    <button @click="counter++">单击+1: {{ counter }}</button>
    <div class="area" v-on="{click: btn1Click, mousemove: mouseMove}">监听鼠标移动事件</div>
    <div class="area" @="{click: btn1Click, mousemove: mouseMove}">监听鼠标移动事件(简写)</div>
</template>
<script src="./js/vue.js"></script>
<script>
    const app = {
        template: '#my-app',
        data() {
            return {
                message: 'Hello World',
                counter: 100
            }
        },
        methods: {
            btn1Click(event) {
                console.log(event);
            },
            btn2Click(event, name) {
                console.log(event, name)
            },
            mouseMove() {
                console.log('鼠标移动')
            }
        }
    }
    Vue.createApp(app).mount('#app')
</script>
</body>
</html>

3. 修饰符

  • 在JavaScript中,可通过event.stopPropagation阻止事件冒泡;在Vue.js 3中,可使用v-on指令的.stop修饰符阻止事件冒泡
...
<template id="my-app">
    <div @click="divClick" :style="{width: '100px', 'height': '65px', backgroundColor:'#ddd'}"
    >
        div
<!--        如果不用.stop修饰符, 那么触发完这个button, 事件会冒泡到父级组件中, 也就是会触发divClick函数-->
        <button @click.stop="btnClick">button按钮</button>
    </div>
<!--    .enter修饰符的作用是只有用户输入enter的时候, 才会触发enterKeyup函数的回调-->    
    <input type="text" @keyup.enter="enterKeyup">
</template>
<script src="./js/vue.js"></script>
<script>
    const app = {
        template: '#my-app',
        data() {
            return {
                message: 'Hello World',
                counter: 100
            }
        },
        methods: {
            divClick() {
                console.log('divClick')
            },
            btnClick() {
                console.log('btnClick')
            },
            enterKeyup(event) {
                console.log('keyup', event.target.value)
            }
        }
    }
    Vue.createApp(app).mount('#app')
</script>
...
  • 如上面代码的演示

条件渲染

  • 在前端开发中,有时需要根据当前条件决定是否渲染特定的元素或组件。Vue.js 3提供了v-if,v-else,v-else-if,v-show指令,用于实现条件判断

v-if

  • 下面的代码实现了单击按钮的时候切换显示和隐藏上面<h2>标签内容的功能
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <div id="app"></div>
    <template id="my-app">
        <h2 v-if="isShow">v-if条件渲染基本使用</h2>
        <button @click="toggle()">单击切换显示和隐藏内容</button>
    </template>
    <script src="./js/vue.js"></script>
    <script>
        const App = {
            template: '#my-app',
            data() {
                return {
                    isShow: true
                }
            },
            methods: {
                toggle() {
                    this.isShow = !this.isShow
                }
            }
        }
        Vue.createApp(App).mount('#app')
    </script>
</body>
</html>
  • 使用v-if指令时,必须将其添加到某一个元素上,,例如<div>元素等,但是如果希望显示和隐藏多个元素,有两种常见的实现方式。第一种是使用<div>元素包裹多个元素,然后使用v-if指令控制该<div>元素的显示和隐藏即可,缺点是<div>元素也会被渲染;第二种实现方式是使用HTML5的<template>包裹多个元素,优点是<template>元素不会被渲染出来,也就是说template不会出现在最终的DOM中,这可以通过js的document.getElementById方法验证。推荐是使用这种方式

v-show

  • v-show也可以用于控制显示和隐藏某一块内容,用法和v-if一致,区别如下
  1. v-show不支持在<template>标签上使用
  2. v-show不可与v-else一起使用
  3. v-show控制的元素无论是否需要显示到浏览器上,它的DOM都会被渲染。本质上是通过CSS的display属性来控制显示和隐藏
  4. v-if的条件为false时,对应的元素不会被渲染到DOM中

开发过程中的选择建议如下

  • 如元素需要在显示和隐藏之间频繁切换,则使用v-show
  • 如不需要频繁切换显示和隐藏,则使用v-if
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <div id="app"></div>
    <template id="my-app">
        <h2 v-if="isShow">v-if控制显示和隐藏</h2>
        <h2 v-show="isShow">v-show控制显示和隐藏</h2>
    </template>
    <script src="./js/vue.js"></script>
    <script>
        const App = {
            template: '#my-app',
            data() {
                return {
                    isShow: false
                }
            }
        }
        Vue.createApp(App).mount('#app')
    </script>
</body>
</html>

在这里插入图片描述

  • 可以看到第一个<h2>不会被渲染到DOM中,第二个<h2>通过CSS的display属性来控制显示和隐藏

列表渲染

  • 在真实的开发过程中,通常需要从服务器获取一组数据并渲染到页面上。这是可以使用Vue.js 3中的v-for指令来实现。v-for指令类似于JavaScript中的for循环,可以用于遍历一组数据,并将每个元素渲染到页面上

v-for

  • 在Vue.js 3中,使用v-for指令语法的方式为v-for="item in 数组"v-for="(item, index) in 数组"
  • 数组:通常来自dataprop,也可以来自methodscomputed
  • item:可以给数组中的每项元素起一个别名,这个别名可以自行命名。item在循环过程中代表当前遍历到的数组元素
  • index:表示当前元素在数组中的索引位置
  • 代码示例如下所示
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <div id="app"></div>
    <template id="my-app">
        <h2>遍历数组</h2>
        <ul>
            <li v-for="j in my_list">
                {{ j }}
            </li>
        </ul>
        <ul>
            <li v-for="(my_l, index) in my_list">
                {{index + 1}}.{{my_l}}
            </li>
        </ul>
    </template>
    <script src="./js/vue.js"></script>
    <script>
        const App = {
            template: '#my-app',
            data() {
                return {
                    my_list: [
                        'first',
                        'second',
                        'third'
                    ]
                }
            }
        }
        Vue.createApp(App).mount('#app')
    </script>
</body>
</html>
  • 此外v-for还支持对象类型和数字类型的遍历

数组的更新检测

  • 在data中定义的变量属于响应式变量,修改这些变量时会自动触发视图的更新。对于定义为数组类型的响应式变量,在调用filter()concat()slice()方法时不会触发视图更新,而调用push()pop()等方法会触发
  • 可以用下面的代码来进行测试
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <div id="app"></div>
    <template id="my-app">
        <h2>遍历数组</h2>
        <ul>
            <li v-for="(my_l, index) in my_list">
                {{index + 1}}.{{my_l}}
            </li>
        </ul>
        <input type="text" v-model="new_list">
        <button @click="addToList">添加</button>
    </template>
    <script src="./js/vue.js"></script>
    <script>
        const App = {
            template: '#my-app',
            data() {
                return {
                    my_list: [
                        'first',
                        'second',
                        'third'
                    ],
                    new_list: ""
                }
            },
            methods: {
                addToList() {
                    this.my_list.push(this.new_list)
                    this.new_list = ""
                }
            }
        }
        Vue.createApp(App).mount('#app')
    </script>
</body>
</html>
  • 13
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Clarence Liu

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值