VueJS 模板语法
Mustache
-
如何将
data
中的文本数据,插入到HTML
中呢?- 我们已经学习过了,可以通过
Mustache
语法(也就是双大括号)。 Mustache
: 胡子/胡须.
- 我们已经学习过了,可以通过
-
我们可以像下面这样来使用,并且数据是响应式的
<!DOCTYPE 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>Document</title> </head> <body> <div id="app"> <h1>{{10+20}}</h1> <h1>{{'hello'+'world'}}</h1> <h1>{{isExists?'存在':'不存在'}}</h1> </div> </body> <script src="../vue.js"></script> <script> const app = new Vue({ el: "#app", data: { isExists: true, }, }); </script> </html>
v-once
-
在某些情况下,我们可能不希望界面随意的跟随改变
- 这个时候,我们就可以使用一个
Vue
的指令
- 这个时候,我们就可以使用一个
-
v-once
:- 该指令后面不需要跟任何表达式(比如之前的
v-for
后面是由跟表达式的) - 该指令表示元素和组件(组件后面才会学习)只渲染一次,不会随着数据的改变而改变。
- 该指令后面不需要跟任何表达式(比如之前的
-
代码如下:
<!DOCTYPE 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>Document</title> </head> <body> <div id="app"> <h1 v-once>{{msg}}</h1> <h1>{{msg}}</h1> </div> </body> <script src="../vue.js"></script> <script> const app = new Vue({ el: "#app", data: { msg: "hello Vuejs", }, }); </script> </html>
v-html
-
某些情况下,我们从服务器请求到的数据本身就是一个
HTML
代码- 如果我们直接通过
{{}}
来输出,会将HTML
代码也一起输出。 - 但是我们可能希望的是按照
HTML
格式进行解析,并且显示对应的内容。
- 如果我们直接通过
-
如果我们希望解析出
HTML
展示-
可以使用
v-html
指令-
该指令后面往往会跟上一个
string
类型 -
会将
string
的html
解析出来并且进行渲染<!DOCTYPE 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>Document</title> </head> <body> <div id="app"> <h1>{{link}}</h1> <h1 v-html="link"></h1> </div> </body> <script src="../vue.js"></script> <script> const app = new Vue({ el: "#app", data: { link: '<a href="http://www.baidu.com/">百度一下</a>', }, }); </script> </html>
-
-
v-text
-
v-text
作用和Mustache
比较相似:都是用于将数据显示在界面中 -
v-text
会将接收到的值展示到界面中<!DOCTYPE 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>Document</title> </head> <body> <div id="app"> <h1>{{msg}}</h1> <h1 v-text="msg"></h1> </div> </body> <script src="../vue.js"></script> <script> const app = new Vue({ el: "#app", data: { msg: "hello Vuejs", }, }); </script> </html>
v-pre
-
v-pre
用于跳过这个元素和它子元素的编译过程,用于显示原本的Mustache
语法。 -
比如下面的代码:
-
第一个
h1
元素中的内容会被编译解析出来对应的内容 -
第二个
h1
元素中会直接显示{{message}}
<!DOCTYPE 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>Document</title> </head> <body> <div id="app"> <h1>{{10+20}}</h1> <h1 v-pre>{{10+20}}</h1> </div> </body> <script src="../vue.js"></script> <script> const app = new Vue({ el: "#app", data: {}, }); </script> </html>
-
v-bind介绍
-
前面我们学习的指令主要作用是将值插入到我们模板的内容当中。
-
但是,除了内容需要动态来决定外,某些属性我们也希望动态来绑定。
- 比如动态绑定
a
元素的href
属性 - 比如动态绑定
img
元素的src
属性
- 比如动态绑定
-
这个时候,我们可以使用
v-bind
指令:- 作用:动态绑定属性
- 缩写:
:
- 预期:
any (with argument) | Object (without argument)
- 参数:
attrOrProp (optional)
v-bind 基础
-
v-bind
用于绑定一个或多个属性值,或者向另一个组件传递props
值(这个学到组件时再介绍) -
在开发中,有哪些属性需要动态进行绑定呢?
-
还是有很多的,比如图片的链接
src
、网站的链接href
、动态绑定一些类、样式等等 -
比如通过
Vue
实例中的data
绑定元素的src
和href
,代码如下:<!DOCTYPE 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>Document</title> </head> <body> <div id="app"> <a href="link">百度</a> <a v-bind:href="link">百度</a> <img v-bind:src="avatar" width="100px" height="100px" /> <img v-bind:src="avatar" v-bind:width="width" v-bind:height="height" /> </div> </body> <script src="../vue.js"></script> <script> const app = new Vue({ el: "#app", data: { link: "https://www.baidu.com/", avatar: "https://lmg.jj20.com/up/allimg/tp09/210Z614150050M-0-lp.jpg", width: "100px", height: "100px", }, }); </script> </html>
-
v-bind 语法糖
-
v-bind
有一个对应的语法糖,也就是简写方式- 在开发中,我们通常会使用语法糖的形式,因为这样更加简洁。
-
简写方式如下:
<!DOCTYPE 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>Document</title> </head> <body> <div id="app"> <a href="link">百度</a> <!-- v-bind 的语法糖 : --> <a :href="link">百度</a> <img :src="avatar" width="100px" height="100px" /> <img :src="avatar" :width="width" :height="height" /> </div> </body> <script src="../vue.js"></script> <script> const app = new Vue({ el: "#app", data: { link: "https://www.baidu.com/", avatar: "https://lmg.jj20.com/up/allimg/tp09/210Z614150050M-0-lp.jpg", width: "100px", height: "100px", }, }); </script> </html>
v-bind 绑定 class(一)
-
很多时候,我们希望动态的来切换class,比如:
- 当数据为某个状态时,字体显示红色。
- 当数据另一个状态时,字体显示黑色。
-
绑定
class
有两种方式:- 对象语法
- 数组语法
v-bind 绑定 class(二)
-
绑定方式:对象语法
- 对象语法的含义是:
class
后面跟的是一个对象。
- 对象语法的含义是:
-
对象语法有下面这些用法:
-
用法一:直接通过
{}
绑定一个类<!DOCTYPE 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>Document</title> <style> .title { font-size: 18px; font-weight: 700; } .active { color: red; } </style> </head> <body> <div id="app"> <h1 class="active">{{msg}}</h1> <h1 :class="{active:true}">{{msg}}</h1> <h1 class="title" :class="{active:false}">{{msg}}</h1> <h1 class="title" :class="{active:true}">{{msg}}</h1> <!-- 直接通过 {} 绑定一个类 也可以与普通 class 进行合并 --> <h1 class="title" :class="{active:isActive}">{{msg}}</h1> </div> </body> <script src="../vue.js"></script> <script> const app = new Vue({ el: "#app", data: { msg: "Hello world", isActive: true, }, }); </script> </html>
-
用法二:也可以通过判断,传入多个值
<!DOCTYPE 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>Document</title> <style> .title { font-size: 18px; font-weight: 700; } .active { color: red; } .line { text-decoration: underline; } </style> </head> <body> <div id="app"> <!-- 用法二:也可以通过判断,代入多个值 --> <p :class="{active:isActive,line:isLine}">{{msg}}</p> </div> </body> <script src="../vue.js"></script> <script> const app = new Vue({ el: "#app", data: { msg: "Hello world", isActive: true, isLine: true, }, }); </script> </html>
-
用法三:和普通的类同时存在,并不冲突
- 注:如果
isActive
和isLine
都为true
,那么会有title/active/line
三个类
<!DOCTYPE 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>Document</title> <style> .title { font-size: 18px; font-weight: 700; } .active { color: red; } .line { text-decoration: underline; } </style> </head> <body> <div id="app"> <p class="title" :class="{active:isActive,line:isLine}">{{msg}}</p> </div> </body> <script src="../vue.js"></script> <script> const app = new Vue({ el: "#app", data: { msg: "Hello world", isActive: true, isLine: true, }, }); </script> </html>
- 注:如果
-
用法四:如果过于复杂,可以放在一个
methods
或者computed
中- 注:
customClass2
是一个计算属性
<!DOCTYPE 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>Document</title> <style> .title { font-size: 18px; font-weight: 700; } .active { color: red; } .line { text-decoration: underline; } </style> </head> <body> <div id="app"> <!-- methods --> <p class="title" :class="customClass()">{{msg}}</p> <!-- computed --> <p class="title" :class="customClass2">{{msg}}</p> </div> </body> <script src="../vue.js"></script> <script> const app = new Vue({ el: "#app", data: { msg: "Hello world", isActive: true, isLine: true, }, computed: { customClass2() { return { active: this.isActive, line: this.isLine, }; }, }, methods: { customClass() { return { active: this.isActive, line: this.isLine, }; }, }, }); </script> </html>
- 注:
-
v-bind 绑定 class(三)
-
绑定方式:数组语法
- 数组语法的含义是:
class
后面跟的是一个数组。
- 数组语法的含义是:
-
数组语法有下面这些用法:
-
用法一:直接通过
[]
定一个类<!DOCTYPE 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>Document</title> <style> .title { font-size: 18px; font-weight: 700; } </style> </head> <body> <div id="app"> <!-- 用法一:直接通过[]定一个类 --> <p :class="['title']">{{msg}}</p> </div> </body> <script src="../vue.js"></script> <script> const app = new Vue({ el: "#app", data: { msg: "Hello world", }, }); </script> </html>
-
用法二:也可以传入多个值
<!DOCTYPE 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>Document</title> <style> .title { font-size: 18px; font-weight: 700; } .active { color: red; } .line { text-decoration: underline; } </style> </head> <body> <div id="app"> <!-- 用法二:也可以传入多个值 --> <p :class="['title','active','line']">{{msg}}</p> </div> </body> <script src="../vue.js"></script> <script> const app = new Vue({ el: "#app", data: { msg: "Hello world", }, }); </script> </html>
-
用法三:和普通的类同时存在,并不冲突
- 注:会有
title/active/line
三个类
<!DOCTYPE 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>Document</title> <style> .title { font-size: 18px; font-weight: 700; } .active { color: red; } .line { text-decoration: underline; } </style> </head> <body> <div id="app"> <!-- 和普通的类同时存在,并不冲突 --> <p class="title" :class="['active','line']">{{msg}}</p> </div> </body> <script src="../vue.js"></script> <script> const app = new Vue({ el: "#app", data: { msg: "Hello world", }, }); </script> </html>
- 注:会有
-
用法四:如果过于复杂,可以放在一个
methods
或者computed
中- 注:
classes
是一个计算属性
<!DOCTYPE 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>Document</title> <style> .title { font-size: 18px; font-weight: 700; } .active { color: red; } .line { text-decoration: underline; } </style> </head> <body> <div id="app"> <!-- methods --> <p class="title" :class="customClass()">{{msg}}</p> <!-- computed --> <p class="title" :class="customClass2">{{msg}}</p> </div> </body> <script src="../vue.js"></script> <script> const app = new Vue({ el: "#app", data: { msg: "Hello world", isActive: true, isLine: true, }, computed: { customClass2() { return ["active", "line"]; }, }, methods: { customClass() { return ["active", "line"]; }, }, }); </script> </html>
- 注:
-
用法五:数组对象
<!DOCTYPE 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>Document</title> <style> .title { font-size: 18px; font-weight: 700; } .active { color: red; } .line { text-decoration: underline; } </style> </head> <body> <div id="app"> <!-- 数组对象 --> <p class="title" :class="[{active:isActive},{line:isLine}]">{{msg}}</p> </div> </body> <script src="../vue.js"></script> <script> const app = new Vue({ el: "#app", data: { msg: "Hello world", isActive: true, isLine: true, }, }); </script> </html>
-
三元表达式
<!DOCTYPE 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>Document</title> <style> .active { color: red; } </style> </head> <body> <div id="app"> <!-- 三元表达式 --> <p :class="[isActive?'active':'']">{{msg}}</p> </div> </body> <script src="../vue.js"></script> <script> const app = new Vue({ el: "#app", data: { msg: "Hello world", isActive: true, isLine: true, }, }); </script> </html>
-
v-bind 绑定 style(一)
-
我们可以利用
v-bind:style
来绑定一些CSS
内联样式。 -
在写
CSS
属性名的时候,比如font-size
- 我们可以使用驼峰式
(camelCase) fontSize
- 或短横线分隔 (
kebab-case
,记得用单引号括起来)‘font-size’
- 我们可以使用驼峰式
-
绑定
style
有两种方式:- 对象语法
- 数组语法
v-bind绑定style(二)
-
绑定方式一:对象语法
<!DOCTYPE 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>Document</title> </head> <body> <div id="app"> <p :style="{color:'red',fontSize:'30px'}">{{msg}}</p> <p :style="{color:'red','font-size':'30px'}">{{msg}}</p> <p :style="{color:isActive?'red':'blue',fontSize}">{{msg}}</p> </div> </body> <script src="../vue.js"></script> <script> const app = new Vue({ el: "#app", data: { msg: "hello world", isActive: false, fontSize: "30px", }, }); </script> </html>
-
绑定方式二:数组语法
<!DOCTYPE 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>Document</title> </head> <body> <div id="app"> <p :style="[a]">{{msg}}</p> </div> </body> <script src="../vue.js"></script> <script> const app = new Vue({ el: "#app", data: { msg: "hello world", a: { color: "red", fontSize: "30px", }, }, }); </script> </html>
什么是计算属性?
-
我们知道,在模板中可以直接通过插值语法显示一些
data
中的数据。 -
但是在某些情况,我们可能需要对数据进行一些转化后再显示,或者需要将多个数据结合起来进行显示
- 比如我们有
firstName
和lastName
两个变量,我们需要显示完整的名称。 - 但是如果多个地方都需要显示完整的名称,我们就需要写多个
{{firstName}} {{lastName}}
- 比如我们有
-
我们可以将上面的代码换成计算属性:
- OK,我们发现计算属性是写在实例的
computed
选项中的。
<!DOCTYPE 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>Document</title> </head> <body> <div id="app"> <h1>{{firstName+lastName}}</h1> <h1>{{firstName}}{{lastName}}</h1> <!-- 计算属性:计算属性使用的时候不加() --> <h1>{{fulleName}}</h1> </div> </body> <script src="../vue.js"></script> <script> const app = new Vue({ el: "#app", data: { firstName: "张", lastName: "三", }, computed: { fulleName() { return this.firstName + this.lastName; }, }, }); </script> </html>
- OK,我们发现计算属性是写在实例的
计算属性的应用
-
计算属性中也可以进行一些更加复杂的操作,比如下面的例子:
<!DOCTYPE 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>Document</title> </head> <body> <div id="app"> <h1>所有图书的总价格:{{totalPrice}}</h1> </div> </body> <script src="../vue.js"></script> <script> const app = new Vue({ el: "#app", data: { books: [ { id: 1, title: "Vuejs开发", price: "70.8", num: 3 }, { id: 2, title: "Nodejs", price: "65.5", num: 2 }, { id: 3, title: "Java", price: "25.5", num: 6 }, { id: 4, title: "JavaScript", price: "35", num: 9 }, ], }, computed: { totalPrice() { // let tPrice = 0; // for (const item of this.books) { // tPrice += item.price * item.num; // } const tPrice = this.books.reduce((pre, item) => { return pre + item.price * item.num; }, 0); return tPrice; }, }, }); </script> </html>
计算属性的 setter 和 getter
-
每个计算属性都包含一个
getter
和一个setter
-
在上面的例子中,我们只是使用
getter
来读取。 -
在某些情况下,你也可以提供一个
setter
方法(不常用)。 -
在需要写
setter
的时候,代码如下:<!DOCTYPE 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>Document</title> </head> <body> <div id="app"> <h1>{{fullName}}</h1> </div> </body> <script src="../vue.js"></script> <script> const app = new Vue({ el: "#app", data: { firstName: "张", lastName: "三", }, computed: { fullName: { get() { console.log("getter"); return this.firstName + this.lastName; }, set(value) { // console.log("setter"); // console.log(value); const valueArray = value.split(" "); this.firstName = valueArray[0]; this.lastName = valueArray[1]; }, }, }, }); </script> </html>
-
计算属性的缓存
-
我们可能会考虑这样的一个问题:
methods
和computed
看起来都可以实现我们的功能,- 那么为什么还要多一个计算属性这个东西呢?
- 原因:计算属性会进行缓存,如果多次使用时,计算属性只会调用一次。
-
我们来看下面的代码:
<!DOCTYPE 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>Document</title> </head> <body> <div id="app"> 计算属性: <h1>{{fullName}}</h1> <h1>{{fullName}}</h1> <h1>{{fullName}}</h1> <h1>{{fullName}}</h1> <h1>{{fullName}}</h1> 方法: <h1>{{fullName2()}}</h1> <h1>{{fullName2()}}</h1> <h1>{{fullName2()}}</h1> <h1>{{fullName2()}}</h1> <h1>{{fullName2()}}</h1> </div> </body> <script src="../vue.js"></script> <script> const app = new Vue({ el: "#app", data: { firstName: "张", lastName: "三", }, computed: { fullName() { console.log("计算属性:fullName"); return this.firstName + this.lastName; }, }, methods: { fullName2() { console.log("methods:fullName2"); return this.firstName + this.lastName; }, }, }); </script> </html>
事件监听
-
在前端开发中,我们需要经常和用于交互。
-
这个时候,我们就必须监听用户发生的时间,比如点击、拖拽、键盘事件等等
-
在
Vue
中如何监听事件呢?使用v-on
指令 -
v-on
介绍- 作用:绑定事件监听器
- 缩写:
@
- 预期:
Function | Inline Statement | Object
- 参数:
event
-
下面,我们就具体来学习
v-on
的使用。
v-on 基础
-
这里,我们用一个监听按钮的点击事件,来简单看看
v-on
的使用-
下面的代码中,我们使用了
v-on:click="counter++”
-
另外,我们可以将事件指向一个在
methods
中定义的函数<!DOCTYPE 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>Document</title> <style> #app { text-align: center; } button { border: none; width: 100px; height: 35px; } </style> </head> <body> <div id="app"> <h1>当前计数:{{counter}}</h1> <button v-on:click="increment">+</button> <button v-on:click="decrement">-</button> </div> </body> <script src="../vue.js"></script> <script> const app = new Vue({ el: "#app", data: { counter: 0, }, methods: { increment(event) { this.counter++; }, decrement(event) { this.counter--; }, }, }); </script> </html>
-
-
注:
v-on
也有对应的语法糖:-
v-on:click
可以写成@click
<!DOCTYPE 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>Document</title> <style> #app { text-align: center; } button { border: none; width: 100px; height: 35px; } </style> </head> <body> <div id="app"> <h1>当前计数:{{counter}}</h1> <button @click="increment">+</button> <button @click="decrement">-</button> </div> </body> <script src="../vue.js"></script> <script> const app = new Vue({ el: "#app", data: { counter: 0, }, methods: { increment(event) { this.counter++; }, decrement(event) { this.counter--; }, }, }); </script> </html>
-
v-on 参数
-
当通过
methods
中定义方法,以供@click
调用时,需要注意参数问题
: -
情况一:如果该方法不需要额外参数,那么方法后的
()
可以不添加。-
但是注意:如果方法本身中有一个参数,那么会默认将原生事件
event
参数传递进去<!DOCTYPE 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>Document</title> </head> <body> <div id="app"> <!-- 当没有传参数 默认会将事件对象传入 --> <button @click="btnClick">按钮1</button> <button @click="btnClick2(10,'hello')">按钮2</button> </div> </body> <script src="../vue.js"></script> <script> const app = new Vue({ el: "#app", methods: { btnClick(event) { console.log(event); }, btnClick2(a, b) { console.log(a, b); }, }, }); </script> </html>
-
-
情况二:如果需要同时传入某个参数,同时需要
event
时,可以通过$event
传入事件。<!DOCTYPE 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>Document</title> </head> <body> <div id="app"> <!-- 传入其他参数的时候,还想使用事件对象,就将$event传入 --> <button @click="btnClick3(10,'hello',$event)">按钮3</button> </div> </body> <script src="../vue.js"></script> <script> const app = new Vue({ el: "#app", methods: { btnClick3(a, b, event) { console.log(a, b, event); }, }, }); </script> </html>
v-on 绑定其他事件
<!DOCTYPE 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>Document</title>
<style>
.box {
width: 50px;
height: 50px;
background: pink;
}
</style>
</head>
<body>
<div id="app">
<input type="text" @input="handleInput" />
<div class="box" @mouseover="handleMouseover"></div>
</div>
</body>
<script src="../vue.js"></script>
<script>
const app = new Vue({
el: "#app",
methods: {
handleInput() {
console.log("handleInput");
},
handleMouseover() {
console.log("handleMouseover");
},
},
});
</script>
</html>
v-on 修饰符
-
在某些情况下,我们拿到
event
的目的可能是进行一些事件处理。 -
Vue
提供了修饰符来帮助我们方便的处理一些事件:-
.stop
- 调用event.stopPropagation()
。<!DOCTYPE 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>Document</title> </head> <body> <div id="app"> <!-- shop 阻止事件的冒泡 --> <div style="width: 150px; height: 150px; background: red" @click="redClick" > <div style="width: 100px; height: 100px; background: black" @click.stop="blackClick" > <div style="width: 50px; height: 50px; background: pink" @click="pinkClick" ></div> </div> </div> </div> </body> <script src="../vue.js"></script> <script> const app = new Vue({ el: "#app", data: {}, methods: { redClick() { console.log("redClick"); }, blackClick() { console.log("blackClick"); }, pinkClick(event) { console.log("pinkClick"); event.stopPropagation(); }, }, }); </script> </html>
-
.prevent
- 调用event.preventDefault()
。<!DOCTYPE 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>Document</title> </head> <body> <div id="app"> <!-- .prevent 阻止默认行为 --> <form action="http://www.baidu.com" @submit.prevent="handleSubmit"> <input type="submit" /> </form> <!-- preventDefault() 阻止默认行为 --> <form action="http://www.baidu.com" @submit="handleSubmit2"> <input type="submit" /> </form> </div> </body> <script src="../vue.js"></script> <script> const app = new Vue({ el: "#app", methods: { handleSubmit() { console.log("提交"); }, handleSubmit2(event) { console.log("提交2"); event.preventDefault(); }, }, }); </script> </html>
-
.{keyCode | keyAlias}
- 只当事件是从特定键触发时才触发回调。<!DOCTYPE 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>Document</title> </head> <body> <div id="app"> <input type="text" @keyup.13="handleKeyup" /> <input type="text" @keyup.enter="handleKeyup" /> </div> </body> <script src="../vue.js"></script> <script> const app = new Vue({ el: "#app", data: {}, methods: { handleKeyup() { console.log("handleKeyup"); }, }, }); </script> </html>
-
.native
- 监听组件根元素的原生事件。 -
.once
- 只触发一次回调。<!DOCTYPE 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>Document</title> </head> <body> <div id="app"> <button @click.once="redClick">按钮</button> </div> </body> <script src="../vue.js"></script> <script> const app = new Vue({ el: "#app", data: {}, methods: { redClick() { console.log("redClick"); }, }, }); </script> </html>
-
v-if、v-else-if、v-else
-
v-if
、v-else-if
、v-else
- 这三个指令与
JavaScript
的条件语句if
、else
、else if
类似。 Vue
的条件指令可以根据表达式的值在DOM
中渲染或销毁元素或组件
- 这三个指令与
-
简单的案例演示:
<!DOCTYPE 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>Document</title> </head> <body> <div id="app"> <p v-if="score>=90">优秀</p> <p v-else-if="score>=70">良好</p> <p v-else-if="score>=60">及格</p> <p v-else>不及格</p> </div> </body> <script src="../vue.js"></script> <script> const app = new Vue({ el: "#app", data: { score: 98, }, }); </script> </html>
-
v-if
的原理:v-if
后面的条件为false
时,对应的元素以及其子元素不会渲染。- 也就是根本没有不会有对应的标签出现在
DOM
中。
条件渲染案例
-
我们来做一个简单的小案例:
-
用户再登录时,可以切换使用用户账号登录还是邮箱地址登录。
-
类似如下情景:
-
案例小问题
- 小问题:
- 如果我们在有输入内容的情况下,切换了类型,我们会发现文字依然显示之前的输入的内容。
- 但是按道理讲,我们应该切换到另外一个
input
元素中了。 - 在另一个
input
元素中,我们并没有输入内容。 - 为什么会出现这个问题呢?
- 问题解答:
- 这是因为
Vue
在进行DOM
渲染时,出于性能考虑,会尽可能的复用已经存在的元素,而不是重新创建新的元素。 - 在上面的案例中,
Vue
内部会发现原来的input
元素不再使用,直接作为else
中的input
来使用了。
- 这是因为
- 解决方案:
- 如果我们不希望
Vue
出现类似重复利用的问题,可以给对应的input
添加key
- 并且我们需要保证
key
的不同
- 如果我们不希望
- 小问题:
-
代码展示
<!DOCTYPE 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>Document</title> </head> <body> <div id="app"> <label for="" v-if="type == 'username'"> 用户账号: <input type="text" placeholder="用户账号" key="username" /> <button @click="handleChange">切换类型</button> </label> <label for="" v-else> 邮箱地址: <input type="text" placeholder="邮箱地址" key="email" /> <button @click="handleChange">切换类型</button> </label> </div> </body> <script src="../vue.js"></script> <script> const app = new Vue({ el: "#app", data: { type: "username", }, methods: { handleChange() { this.type = this.type == "username" ? "email" : "username"; }, }, }); </script> </html>
-
v-show
-
v-show
的用法和v-if
非常相似,也用于决定一个元素是否渲染:<!DOCTYPE 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>Document</title> </head> <body> <div id="app"> <h1 v-show="isShow">hello</h1> <button @click="toggleHide">切换显示</button> <!-- if 和 v-show 的区别 --> <!-- 1. v-if 切换重新创建或者销毁元素或者组件 v-show 设置display属性 2. v-if 性能消耗大 v-show 性能消耗小 3. 当切换频率高的时候,使用v-show 当切换频率低的时候,使用v-if --> </div> </body> <script src="../vue.js"></script> <script> const app = new Vue({ el: "#app", data: { isShow: true, }, methods: { toggleHide() { this.isShow = !this.isShow; }, }, }); </script> </html>
-
v-if
和v-show
对比 -
v-if
和v-show
都可以决定一个元素是否渲染,那么开发中我们如何选择呢?-
v-if
当条件为false
时,压根不会有对应的元素在DOM
中。 -
v-show
当条件为false
时,仅仅是将元素的display
属性设置为none
而已。
-
-
开发中如何选择呢?
- 当需要在显示与隐藏之间切片很频繁时,使用
v-show
- 当只有一次切换时,通过使用
v-if
- 当需要在显示与隐藏之间切片很频繁时,使用
v-for 遍历数组
-
当我们有一组数据需要进行渲染时,我们就可以使用
v-for
来完成。v-for
的语法类似于JavaScript
中的for
循环。- 格式如下:
item in items
的形式。
-
我们来看一个简单的案例:
<!DOCTYPE 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>Document</title> </head> <body> <div id="app"> <ul> <li v-for="(item,index) in movies">{{index}}.{{item}}</li> </ul> </div> </body> <script src="../vue.js"></script> <script> const app = new Vue({ el: "#app", data: { movies: ["盗梦空间", "西游记", "三国演义", "红楼梦"], }, }); </script> </html>
-
如果在遍历的过程中不需要使用索引值
v-for="item in movies"
- 依次从
movies
中取出item
,并且在元素的内容中,我们可以使用Mustache
语法,来使用item
-
如果在遍历的过程中,我们需要拿到元素在数组中的索引值呢?
- 语法格式:
v-for=(item, index) in items
- 其中的
index
就代表了取出的item
在原数组的索引值。
- 语法格式:
v-for 遍历对象
-
v-for
可以用户遍历对象: -
比如某个对象中存储着你的个人信息,我们希望以列表的形式显示出来。
<!DOCTYPE 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>Document</title> </head> <body> <div id="app"> <p v-for="(value,key,index) in person">{{index}}-{{key}}-{{value}}</p> </div> </body> <script src="../vue.js"></script> <script> const app = new Vue({ el: "#app", data: { person: { name: "张三", age: 18, height: 188, }, }, }); </script> </html>
检测数组更新
-
因为
Vue
是响应式的,所以当数据发生变化时,Vue
会自动检测数据变化,视图会发生对应的更新。 -
Vue
中包含了一组观察数组编译的方法,使用它们改变数组也会触发视图的更新。push()
pop()
shift()
unshift()
splice()
sort()
reverse()
-
代码案例展示
<!DOCTYPE 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>Document</title> </head> <body> <div id="app"> <h1>{{names}}</h1> <h1>{{abc}}</h1> <button @click="handleEditClick">更新数组</button> </div> </body> <script src="../vue.js"></script> <script> const app = new Vue({ el: "#app", data: { names: ["张三", "李四"], abc: [1, 11, 23, 10, 8, 3, 9], }, methods: { handleEditClick() { // 添加元素 // this.names.push("王五", "赵六"); // 删除最后一个 // this.names.pop(); // 删除第一个元素 // this.names.shift(); // 在数组的首位添加一个元素 // this.names.unshift("小刘") // 删除 this.names.splice(1, 1); // 插入 this.names.splice(1, 0, "赵六"); // 替换 this.names.splice(1, 1, "马奇"); // 排序 this.abc.sort((a, b) => a - b); // 数组反转 this.abc.reverse(); }, }, }); </script> </html>
数组的注意事项(Vue.set)
-
<!DOCTYPE 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>Document</title> </head> <body> <div id="app"> <h1>{{names}}</h1> <h1>{{obj}}</h1> <button @click="handleEditClick">更新数组</button> <button @click="handleEditAgeClick">更新年龄</button> </div> </body> <script src="../vue.js"></script> <script> const app = new Vue({ el: "#app", data: { names: ["张三", "李四"], obj: {}, }, methods: { handleEditClick() { // 这个操作是不行的 // this.names[1] = "王五"; // 数据发了改变但是页面没有发生改变 说明数据没有实现双向绑定 // console.log(this.names); // ['张三', '王五', __ob__: Observer] // 数组: Vue.set(数组, 下标, value) Vue.set(this.names, 1, "王五"); // this.obj.age = 19 这种方式添加的属性是不具备双向绑定能力的 // 对象: Vue.set(对象, key, value); Vue.set(this.obj, "age", 19); }, // 更改对象中的属性 handleEditAgeClick() { this.obj.age = 100; }, }, }); </script> </html>
过滤器-filters
-
Vue.js
允许你自定义过滤器,可被用于一些常见的文本格式化。过滤器可以用在两个地方:双花括号插值和v-bind
表达式 (后者从2.1.0+
开始支持)。过滤器应该被添加在JavaScript
表达式的尾部,由“管道”
(|
)符号指示:-
在
v-bind
中使用<!DOCTYPE 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>Document</title> <link rel="stylesheet" href="https://at.alicdn.com/t/c/font_3464777_0ncyua7qfzac.css" /> </head> <body> <div id="app"> <h1 :class="'xiezi'| fontIcon"></h1> <h1 :class="'dianpu'| fontIcon"></h1> </div> </body> <script src="../vue.js"></script> <script> const app = new Vue({ el: "#app", data: {}, filters: { fontIcon(icon) { console.log(icon); return "iconfont icon-" + icon; }, }, }); </script> </html>
-
在双花括号中使用
<!DOCTYPE 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>Document</title> </head> <body> <div id="app"> <h1>{{80|showPrice}}</h1> </div> </body> <script src="../vue.js"></script> <script> const app = new Vue({ el: "#app", data: {}, filters: { showPrice(price) { return "¥" + price.toFixed(2); }, }, }); </script> </html>
-
过滤器-参数问题
-
过滤器函数总接收表达式的值 (之前的操作链的结果) 作为第一个参数。在上述例子中,
showPrice
过滤器函数将会收到message
的值作为第一个参数 -
过滤器是
JavaScript
函数,因此可以接收参数: -
这里,
showPrice
被定义为接收三个参数的过滤器函数。其中80
的值作为第一个参数,普通字符串10
作为第二个参数,表达式admin
的值作为第三个参数<!DOCTYPE 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>Document</title> </head> <body> <div id="app"> <p>{{80|showPrice(10,'admin')}}</p> </div> </body> <script src="../vue.js"></script> <script> const app = new Vue({ el: "#app", data: {}, filters: { showPrice(price, a, b) { console.log(price, a, b); return price; }, }, }); </script> </html>
串联-过滤器
-
过滤器可以串联:
-
在这个例子中,
filterA
被定义为接收单个参数的过滤器函数,表达式message
的值将作为参数传入到函数中。然后继续调用同样被定义为接收单个参数的过滤器函数filterB
,将filterA
的结果传递到filterB
中。<!DOCTYPE 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>Document</title> </head> <body> <div id="app"> <p>{{80|filterA|filterB}}</p> </div> </body> <script src="../vue.js"></script> <script> const app = new Vue({ el: "#app", data: {}, filters: { filterA(a) { return a + 10; }, filterB(b) { return b + 10; }, }, }); </script> </html>
表单绑定 v-model
-
表单控件在实际开发中是非常常见的。特别是对于用户信息的提交,需要大量的表单。
-
Vue
中使用v-model
指令来实现表单元素和数据的双向绑定。 -
案例的解析:
-
当我们在输入框输入内容时
-
因为
input
中的v-model
绑定了message
,所以会实时将输入的内容传递给message
,message
发生改变。 -
当
message
发生改变时,因为上面我们使用Mustache
语法,将message
的值插入到DOM
中,所以DOM
会发生响应的改变。 -
所以,通过
v-model
实现了双向的绑定。 -
当然,我们也可以将
v-model
用于textarea
元素<!DOCTYPE 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>Document</title> </head> <body> <div id="app"> <input type="text" v-model="message" /> <textarea v-model="message"></textarea> <h1>{{ message }}</h1> </div> </body> <script src="../vue.js"></script> <script> const app = new Vue({ el: "#app", data: { message: "Hello World", }, }); </script> </html>
v-model 原理
-
v-model
其实是一个语法糖,它的背后本质上是包含两个操作:- 1.
v-bind
绑定一个value
属性 - 2.
v-on
指令给当前元素绑定input
事件
- 1.
-
也就是说下面的代码:等同于下面的代码:
<!DOCTYPE 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>Document</title> </head> <body> <div id="app"> <input type="text" v-model="message" /> <input type="text" :value="message" @input="handleModel" /> <input type="radio" value="男" :checked="gander=='男'" @change="handelChange" /> <input type="radio" value="女" :checked="gander=='女'" @change="handelChange" /> <h1>{{ message }}</h1> </div> </body> <script src="../vue.js"></script> <script> const app = new Vue({ el: "#app", data: { message: "Hello World", gander: "男", }, methods: { handleModel(event) { this.message = event.target.value; }, handelChange(event) { this.gander = event.target.value; }, }, }); </script> </html>
v-model:radio
-
当存在多个单选框时
<!DOCTYPE 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>Document</title> </head> <body> <div id="app"> <!-- 多个单选框 --> <label for=""> 唱:<input type="radio" value="唱" v-model="like" /> </label> <label for=""> 跳:<input type="radio" value="跳" v-model="like" /> </label> <label for=""> rap:<input type="radio" value="rap" v-model="like" /> </label> <label for=""> 篮球:<input type="radio" value="篮球" v-model="like" /> </label> <p>{{like}}</p> <label for=""> 男:<input type="radio" value="男" v-model="gander" /> </label> <label for=""> 女:<input type="radio" value="女" v-model="gander" /> </label> <p>{{gander}}</p> </div> </body> <script src="../vue.js"></script> <script> const app = new Vue({ el: "#app", data: { like: "", gander: "", }, }); </script> </html>
v-model:checkbox
-
复选框分为两种情况:单个勾选框和多个勾选框
-
单个勾选框:
-
v-model
即为布尔值。 -
此时
input
的value
并不影响v-model
的值。<!DOCTYPE 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>Document</title> </head> <body> <div id="app"> <!-- 单个复选框 复选框单选 --> <label for=""> <input type="checkbox" v-model="checked" /> </label> <p>{{checked}}</p> </div> </body> <script src="../vue.js"></script> <script> const app = new Vue({ el: "#app", data: { checked: false, }, }); </script> </html>
-
-
多个复选框:
-
当是多个复选框时,因为可以选中多个,所以对应的
data
中属性是一个数组。 -
当选中某一个时,就会将
input
的value
添加到数组中。<!DOCTYPE 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>Document</title> </head> <body> <div id="app"> <!-- 复选框多选 --> <label for=""> 吃饭:<input type="checkbox" value="吃饭" v-model="like" /> </label> <label for=""> 睡觉:<input type="checkbox" value="睡觉" v-model="like" /> </label> <label for=""> 写代码:<input type="checkbox" value="写代码" v-model="like" /> </label> <p>{{like}}</p> </div> </body> <script src="../vue.js"></script> <script> const app = new Vue({ el: "#app", data: { like: [], }, }); </script> </html>
-
v-model:select
-
和
checkbox
一样,select
也分单选和多选两种情况。 -
单选:只能选中一个值。
-
v-model
绑定的是一个值。 -
当我们选中
option
中的一个时,会将它对应的value
赋值到mySelect
中<!DOCTYPE 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>Document</title> <style> select { width: 100%; border: 1px solid aqua; outline: 1px solid aqua; } </style> </head> <body> <div id="app"> <select v-model="city"> <option value="西安">西安</option> <option value="宝鸡">宝鸡</option> <option value="咸阳">咸阳</option> </select> <p>{{city}}</p> </div> </body> <script src="../vue.js"></script> <script> const app = new Vue({ el: "#app", data: { city: "", }, }); </script> </html>
-
修饰符
-
lazy
修饰符:-
默认情况下,
v-model
默认是在input
事件中同步输入框的数据的。 -
也就是说,一旦有数据发生改变对应的
data
中的数据就会自动发生改变。 -
lazy
修饰符可以让数据在失去焦点或者回车时才会更新:<!DOCTYPE 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>Document</title> </head> <body> <div id="app"> <input type="text" v-model.lazy="message" /> <p>{{message}}</p> </div> </body> <script src="../vue.js"></script> <script> const app = new Vue({ el: "#app", data: { message: "消息", }, }); </script> </html>
-
-
number
修饰符:-
默认情况下,在输入框中无论我们输入的是字母还是数字,都会被当做字符串类型进行处理。
-
但是如果我们希望处理的是数字类型,那么最好直接将内容当做数字处理。
-
number
修饰符可以让在输入框中输入的内容自动转成数字类型:<!DOCTYPE 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>Document</title> </head> <body> <div id="app"> <input type="text" v-model.number="counter" /> <p>{{typeof counter}}</p> </div> </body> <script src="../vue.js"></script> <script> const app = new Vue({ el: "#app", data: { counter: 0, }, }); </script> </html>
-
-
trim
修饰符:-
如果输入的内容首尾有很多空格,通常我们希望将其去除
-
trim
修饰符可以过滤内容左右两边的空格<!DOCTYPE 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>Document</title> </head> <body> <div id="app"> <input type="text" v-model.trim="message" /> <p>{{ message.length }}</p> </div> </body> <script src="../vue.js"></script> <script> const app = new Vue({ el: "#app", data: { message: "消息", }, }); </script> </html>
-