练习模板:
components:
src/ components/ MyComponent.vue
<template>
<button @click="count++"> count is:{{ count }}</button>
</template>
<style scoped lang="scss">
button {
font-weight: bold;
}
</style>
<script>
export default {
name: "MyComponent",
data(){
return {count:0}
}
}
</script>
views:
src/ views/ TestView.vue
<template>
<div class="test">
<h1>This is an test page</h1>
<MyComponent />
</div>
</template>
<script>
// @ is an alias to /src
import MyComponent from '@/components/MyComponent.vue'
export default {
name:'TestView',
components: {
MyComponent
}
}
</script>
router:
src/ router/ index.js
import { createRouter, createWebHistory } from 'vue-router'
import HomeView from '../views/HomeView.vue'
import TestView from '../views/TestView.vue'
const routes = [
{
path: '/',
name: 'home',
component: HomeView
},
{
path: '/about',
name: 'about',
// route level code-splitting
// this generates a separate chunk (about.[hash].js) for this route
// which is lazy-loaded when the route is visited.
component: () => import(/* webpackChunkName: "about" */ '../views/AboutView.vue')
},
{
path: '/test',
name: 'test',
component: TestView
}
]
const router = createRouter({
history: createWebHistory(process.env.BASE_URL),
routes
})
export default router
App.vue
src/ App.vue
<template>
<nav>
<router-link to="/">Home</router-link> |
<router-link to="/about">About</router-link> |
<router-link to="/test">Test</router-link>
</nav>
<router-view/>
</template>
<style lang="scss">
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
}
nav {
padding: 30px;
a {
font-weight: bold;
color: #2c3e50;
&.router-link-exact-active {
color: #42b983;
}
}
}
</style>
<script setup lang="ts">
</script>
路由链接: <router-link to="/test">Test</router-link>
路由引用展示:<router-view/>
---------------------------------------上述为练习用的基础模板与路由(基于vue3)---------------------
1.文本插值
{{}} == v-text
MyComponent.vue
<template>
<div class="test-title">模板语法</div>
<div class="test-direct"> <p>\{\{}},v-text :</p></div>
<div class="test-show">
<p> <button @click="count++"> count is+ :{{ count }} </button> </p>
<p> <button @click="modify">点击修改文本信息</button><br> </p>
<p> <span v-text="msg"></span> </p>
<!-- 等同于 -->
<p> <span> == {{msg}}</span></p>
</div>
</template>
<style scoped lang="scss">
button {
font-weight: bold;
}
.test-title {
font-weight: bold;
color: #080899;
margin-left: 0px;
text-align: left;
}
.test-direct {
font-weight: bold;
color: #000000;
margin-left: 40px;
text-align: left;
}
.test-show {
font-weight: bold;
color: #42b983;
margin-left: 150px;
text-align: left;
}
</style>
<script>
export default {
name: "MyComponent",
data(){
return {
count:0,
msg:"测试信息"
}
},
//所有页面中要用到方法
methods:{
modify:function(){
this.msg="修改了测试信息" + this.count
}
}
}
</script>
效果:
2.v-html
v-html
的内容直接作为普通 HTML 插入—— Vue 模板语法是不会被解析的。如果你发现自己正打算用 v-html
来编写模板,不如重新想想怎么使用组件来代替。
MyComponent.vue
<template>
<div class="test-title">模板语法</div>
<div class="test-direct"> <p>\{\{}},v-text :</p></div>
<div class="test-show">
<p> <button @click="count++"> count is+ :{{ count }} </button> </p>
<p> <button @click="modify">点击修改文本信息</button><br> </p>
<p> <span v-text="msg"></span> </p>
<!-- 等同于 -->
<p> <span> == {{msg}}</span></p>
</div>
<p></p>
<div class="test-direct"> <p>v-html :</p></div>
<div class="test-show">
<p>v-html</p>
<p>Using text interpolation: {{ rawHtml }}</p>
<p>Using v-html directive: <span v-html="rawHtml"></span></p>
</div>
</template>
<style scoped lang="scss">
button {
font-weight: bold;
}
.test-title {
font-weight: bold;
color: #080899;
margin-left: 0px;
text-align: left;
}
.test-direct {
font-weight: bold;
color: #000000;
margin-left: 40px;
text-align: left;
}
.test-show {
font-weight: bold;
color: #42b983;
margin-left: 150px;
text-align: left;
}
</style>
<script>
export default {
name: "MyComponent",
data(){
return {
count:0,
msg:"测试信息",
rawHtml:'Using text interpolation: <span style="color: red">This should be red.</span>'
}
},
//所有页面中要用到方法
methods:{
modify:function(){
this.msg="修改了测试信息" + this.count
}
}
}
</script>
3.v-show
基于表达式值的真假性,来改变元素的可见性。
-
期望的绑定值类型:
any
-
详细信息
v-show
通过设置内联样式的display
CSS 属性来工作,当元素可见时将使用初始display
值。当条件改变时,也会触发过渡效果。
v-show
不支持在 <template>
元素上使用,也不能和 v-else
搭配使用。
MyComponent.vue
<template>
<div class="test-title">模板语法</div>
<div class="test-direct"> <p>\{\{}},v-text :</p></div>
<div class="test-show">
<p> <button @click="count++"> count is+ :{{ count }} </button> </p>
<p> <button @click="modify">点击修改文本信息</button><br> </p>
<p> <span v-text="msg"></span> </p>
<!-- 等同于 -->
<p> <span> == {{msg}}</span></p>
</div>
<p></p>
<div class="test-direct"> <p>v-html :</p></div>
<div class="test-show">
<p>v-html</p>
<p>Using text interpolation: {{ rawHtml }}</p>
<p>Using v-html directive: <span v-html="rawHtml"></span></p>
</div>
<p></p>
<div class="test-direct"> <p>v-show :</p></div>
<div class="test-show">
<p>v-show</p>
<p> <span><h1 v-show="ok"> {{ok}},Hello!</h1></span></p>
</div>
</template>
<style scoped lang="scss">
button {
font-weight: bold;
}
.test-title {
font-weight: bold;
color: #080899;
margin-left: 0px;
text-align: left;
}
.test-direct {
font-weight: bold;
color: #000000;
margin-left: 40px;
text-align: left;
}
.test-show {
font-weight: bold;
color: #42b983;
margin-left: 150px;
text-align: left;
}
</style>
<script>
export default {
name: "MyComponent",
data(){
return {
count:0,
msg:"测试信息",
rawHtml:'Using text interpolation: <span style="color: red">This should be red.</span>',
ok: true
}
},
//所有页面中要用到方法
methods:{
modify:function(){
this.msg="修改了测试信息" + this.count
}
}
}
</script>
4. v-if
/ v-else-if/v-else
MyComponent.vue
<div class="test-direct"> <p>v-if/v-else-if/v-else :</p></div>
<div class="test-show">
<span v-if="rv > 0.5">
Now you see me
</span>
<span v-else>
Now you don't
</span>
</div>
<script>
export default {
name: "MyComponent",
data(){
return {
count:0,
msg:"测试信息",
rawHtml:'Using text interpolation: <span style="color: red">This should be red.</span>',
ok: true,
rv:Math.random()
}
},
//所有页面中要用到方法
methods:{
modify:function(){
this.msg="修改了测试信息" + this.count
}
}
}
</script>
5.v-for
基于原始数据多次渲染元素或模板块。
-
期望的绑定值类型:
Array | Object | number | string | Iterable
-
详细信息
指令值必须使用特殊语法
alias in expression
为正在迭代的元素提供一个别名:
语法:
<div v-for="item in items">
{{ item.text }}
</div>
或者,你也可以为索引指定别名 (如果用在对象,则是键值):
<div v-for="(item, index) in items"></div>
<div v-for="(value, key) in object"></div>
<div v-for="(value, name, index) in object"></div>
v-for 的默认方式是尝试就地更新元素而不移动它们。要强制其重新排序元素,你需要用特殊 attribute key 来提供一个排序提示:
<div v-for="item in items" :key="item.id">
{{ item.text }}
</div>
v-for 也可以用于 Iterable Protocol 的实现,包括原生 Map 和 Set。
MyComponent.vue
<div class="test-direct"> <p>v-for :</p></div>
<div class="test-show">
<ul>
<li v-for="item in items" v-bind:key="item.message">
{{ item.message }}
</li>
</ul>
<h1>--------------------</h1>
<ul>
<li v-for="(item,index) in items" v-bind:key="index">
{{index}}------------>{{ item.message }}
</li>
</ul>
<h1>--------------------</h1>
<ul>
<li v-for="(item, index) in items" v-bind:key="index">
{{ parentMessage }} - {{ index }} - {{ item.message }}
</li>
</ul>
</div>
<script>
export default {
name: "MyComponent",
data(){
return {
count:0,
msg:"测试信息",
rawHtml:'Using text interpolation: <span style="color: red">This should be red.</span>',
ok: true,
rv:Math.random(),
parentMessage: 'Parent',
items: [{ message: 'Foo' }, { message: 'Bar' }]
}
},
//所有页面中要用到方法
methods:{
modify:function(){
this.msg="修改了测试信息" + this.count
}
}
}
</script>
6.v-on
给元素绑定事件监听器。
-
缩写:
@
-
期望的绑定值类型:
Function | Inline Statement | Object (不带参数)
-
参数:
event
(使用对象语法则为可选项) -
修饰符
-
.stop
- 调用event.stopPropagation()
。 .prevent
- 调用event.preventDefault()
。.capture
- 在捕获模式添加事件监听器。.self
- 只有事件从元素本身发出才触发处理函数。.{keyAlias}
- 只在某些按键下触发处理函数。.once
- 最多触发一次处理函数。.left
- 只在鼠标左键事件触发处理函数。.right
- 只在鼠标右键事件触发处理函数。.middle
- 只在鼠标中键事件触发处理函数。.passive
- 通过{ passive: true }
附加一个 DOM 事件。
-
详细信息
事件类型由参数来指定。表达式可以是一个方法名,一个内联声明,如果有修饰符则可省略。
当用于普通元素,只监听原生 DOM 事件。当用于自定义元素组件,则监听子组件触发的自定义事件。
当监听原生 DOM 事件时,方法接收原生事件作为唯一参数。如果使用内联声明,声明可以访问一个特殊的 $event
变量:v-on:click="handle('ok', $event)"
。
v-on
还支持绑定不带参数的事件/监听器对的对象。请注意,当使用对象语法时,不支持任何修饰符。
示例
<!-- 方法处理函数 -->
<button v-on:click="doThis"></button>
<!-- 动态事件 -->
<button v-on:[event]="doThis"></button>
<!-- 内联声明 -->
<button v-on:click="doThat('hello', $event)"></button>
<!-- 缩写 -->
<button @click="doThis"></button>
<!-- 使用缩写的动态事件 -->
<button @[event]="doThis"></button>
<!-- 停止传播 -->
<button @click.stop="doThis"></button>
<!-- 阻止默认事件 -->
<button @click.prevent="doThis"></button>
<!-- 不带表达式地阻止默认事件 -->
<form @submit.prevent></form>
<!-- 链式调用修饰符 -->
<button @click.stop.prevent="doThis"></button>
<!-- 按键用于 keyAlias 修饰符-->
<input @keyup.enter="onEnter" />
<!-- 点击事件将最多触发一次 -->
<button v-on:click.once="doThis"></button>
<!-- 对象语法 -->
<button v-on="{ mousedown: doThis, mouseup: doThat }"></button>
监听子组件的自定义事件 (当子组件的“my-event”事件被触发,处理函数将被调用):
<MyComponent @my-event="handleThis" />
<!-- 内联声明 -->
<MyComponent @my-event="handleThis(123, $event)" />
MyComponent.vue
<p></p>
<div class="test-direct"> <p>v-on :</p></div>
<div class="test-show">
<p> <button v-on:click="doThis">点击click事件, v-on==@</button><br> </p>
<p> <span>点击结果:{{msg}}</span></p>
</div>
<script>
export default {
name: "MyComponent",
data(){
return {
count:0,
msg:"测试信息",
rawHtml:'Using text interpolation: <span style="color: red">This should be red.</span>',
ok: true,
rv:Math.random(),
parentMessage: 'Parent',
items: [{ message: 'Foo' }, { message: 'Bar' }]
}
},
//所有页面中要用到方法
methods:{
modify:function(){
this.msg="修改了测试信息" + this.count
},
doThis:function (){
this.msg="click 触发。"
}
}
}
</script>
7.v-bind
动态的绑定一个或多个 attribute,也可以是组件的 prop。
缩写:
:
或者.
(当使用.prop
修饰符)- 值可以省略 (当 attribute 和绑定的值同名时)
期望:any (带参数) | Object (不带参数)
参数:attrOrProp (可选的)
修饰符
.camel
- 将短横线命名的 attribute 转变为驼峰式命名。.prop
- 强制绑定为 DOM property。.attr
- 强制绑定为 DOM attribute。
用途
当用于绑定 class
或 style
attribute,v-bind
支持额外的值类型如数组或对象。详见下方的指南链接。
在处理绑定时,Vue 默认会利用 in
操作符来检查该元素上是否定义了和绑定的 key 同名的 DOM property。如果存在同名的 property,则 Vue 会将它作为 DOM property 赋值,而不是作为 attribute 设置。这个行为在大多数情况都符合期望的绑定值类型,但是你也可以显式用 .prop
和 .attr
修饰符来强制绑定方式。有时这是必要的,特别是在和自定义元素打交道时。
当用于组件 props 绑定时,所绑定的 props 必须在子组件中已被正确声明。
-
当不带参数使用时,可以用于绑定一个包含了多个 attribute 名称-绑定值对的对象
示例
<!-- 绑定 attribute -->
<img v-bind:src="imageSrc" />
<!-- 动态 attribute 名 -->
<button v-bind:[key]="value"></button>
<!-- 缩写 -->
<img :src="imageSrc" />
<!-- 缩写形式的动态 attribute 名 (3.4+),扩展为 :src="src" -->
<img :src />
<!-- 动态 attribute 名的缩写 -->
<button :[key]="value"></button>
<!-- 内联字符串拼接 -->
<img :src="'/path/to/images/' + fileName" />
<!-- class 绑定 -->
<div :class="{ red: isRed }"></div>
<div :class="[classA, classB]"></div>
<div :class="[classA, { classB: isB, classC: isC }]"></div>
<!-- style 绑定 -->
<div :style="{ fontSize: size + 'px' }"></div>
<div :style="[styleObjectA, styleObjectB]"></div>
<!-- 绑定对象形式的 attribute -->
<div v-bind="{ id: someProp, 'other-attr': otherProp }"></div>
<!-- prop 绑定。“prop” 必须在子组件中已声明。 -->
<MyComponent :prop="someThing" />
<!-- 传递子父组件共有的 prop -->
<MyComponent v-bind="$props" />
<!-- XLink -->
<svg><a :xlink:special="foo"></a></svg>
.prop
修饰符也有专门的缩写,.
:
<div :someProperty.prop="someObject"></div>
<!-- 等同于 -->
<div .someProperty="someObject"></div>
当在 DOM 内模板使用 .camel
修饰符,可以驼峰化 v-bind
attribute 的名称,例如 SVG viewBox
attribute:
<svg :view-box.camel="viewBox"></svg>
如果使用字符串模板或使用构建步骤预编译模板,则不需要 .camel
。
8.v-model
在表单输入元素或组件上创建双向绑定。
-
期望的绑定值类型:根据表单输入元素或组件输出的值而变化
-
仅限:
<input>
<select>
<textarea>
- components
- 修饰符
- 参考
- 表单输入绑定
- 组件事件 - 配合 v-model 使用
MyComponent.vue
<div class="test-direct"> <p>v-model :</p></div>
<div class="test-show">
<p>Message is: {{ msg }}</p>
<input v-model="msg" placeholder="edit me" />
</div>
<script>
export default {
name: "MyComponent",
data(){
return {
count:0,
msg:"测试信息",
rawHtml:'Using text interpolation: <span style="color: red">This should be red.</span>',
ok: true,
rv:Math.random(),
parentMessage: 'Parent',
items: [{ message: 'Foo' }, { message: 'Bar' }]
}
},
//所有页面中要用到方法
methods:{
modify:function(){
this.msg="修改了测试信息" + this.count
},
doThis:function (){
this.msg="click 触发。"
}
}
}
</script>
文本:
同上个例子
多行文本:
MyComponent.vue
<div class="test-direct"> <p>v-model :多行文本</p></div>
<div class="test-show">
<p>Multiline message is:</p>
<p style="white-space: pre-line;">{{ msg }}</p>
<textarea v-model="msg" placeholder="add multiple lines"></textarea>
</div>
复选框:
MyComponent.vue
<div class="test-direct"> <p>v-model :复选框</p></div>
<div class="test-show">
<input type="checkbox" id="checkbox" v-model="checked" />
<label for="checkbox">{{ checked }}</label>
<input type="checkbox" id="checkbox" v-model="checked" />
<label for="checkbox">{{ checked2 }}</label>
</div>
<script>
export default {
name: "MyComponent",
data(){
return {
count:0,
msg:"测试信息",
rawHtml:'Using text interpolation: <span style="color: red">This should be red.</span>',
ok: true,
rv:Math.random(),
parentMessage: 'Parent',
items: [{ message: 'Foo' }, { message: 'Bar' }],
checked: true,
checked2: false
}
},
//所有页面中要用到方法
methods:{
modify:function(){
this.msg="修改了测试信息" + this.count
},
doThis:function (){
this.msg="click 触发。"
}
}
}
</script>
单选按钮:
MyComponent.vue
<div class="test-direct"> <p>v-model :单选按钮</p></div>
<div class="test-show">
<div>Picked: {{ picked }}</div>
<input type="radio" id="one" value="One" v-model="picked" />
<label for="one">One</label>
<input type="radio" id="two" value="Two" v-model="picked" />
<label for="two">Two</label>
</div>
script>
export default {
name: "MyComponent",
data(){
return {
count:0,
msg:"测试信息",
rawHtml:'Using text interpolation: <span style="color: red">This should be red.</span>',
ok: true,
rv:Math.random(),
parentMessage: 'Parent',
items: [{ message: 'Foo' }, { message: 'Bar' }],
checked: true,
checked2: false,
picked: 'One'
}
},
//所有页面中要用到方法
methods:{
modify:function(){
this.msg="修改了测试信息" + this.count
},
doThis:function (){
this.msg="click 触发。"
}
}
}
</script>
选择器:
MyComponent.vue
单选
<div class="test-direct"> <p>v-model :选择器-单选</p></div>
<div class="test-show">
<div>SelectedOne: {{ selectedOne }}</div>
<select v-model="selectedOne">
<option disabled value="">Please select one</option>
<option>A</option>
<option>B</option>
<option>C</option>
</select>
</div>
多选(值绑定到一个数组)
<div class="test-direct"> <p>v-model :选择器-多选(值绑定到一个数组)</p></div>
<div class="test-show">
<div>selectedMany: {{ selectedMany }}</div>
<select v-model="selectedMany" multiple>
<option>A</option>
<option>B</option>
<option>C</option>
</select>
</div>
<script>
export default {
name: "MyComponent",
data(){
return {
count:0,
msg:"测试信息",
rawHtml:'Using text interpolation: <span style="color: red">This should be red.</span>',
ok: true,
rv:Math.random(),
parentMessage: 'Parent',
items: [{ message: 'Foo' }, { message: 'Bar' }],
checked: true,
checked2: false,
picked: 'One',
selectedOne:'',
selectedMany: []
}
},
//所有页面中要用到方法
methods:{
modify:function(){
this.msg="修改了测试信息" + this.count
},
doThis:function (){
this.msg="click 触发。"
}
}
}
</script>
<style scoped lang="scss">
select[multiple] {
width: 100px;
}
</style>
值绑定:
对于单选按钮,复选框和选择器选项,v-model
绑定的值通常是静态的字符串 (或者对复选框是布尔值):
<!-- `picked` 在被选择时是字符串 "a" -->
<input type="radio" v-model="picked" value="a" />
<!-- `toggle` 只会为 true 或 false -->
<input type="checkbox" v-model="toggle" />
<!-- `selected` 在第一项被选中时为字符串 "abc" -->
<select v-model="selected">
<option value="abc">ABC</option>
</select>
但有时我们可能希望将该值绑定到当前组件实例上的动态数据。这可以通过使用 v-bind
来实现。此外,使用 v-bind
还使我们可以将选项值绑定为非字符串的数据类型。
复选框
<input type="checkbox" v-model="toggle" true-value="yes" false-value="no" />
true-value
和 false-value
是 Vue 特有的 attributes,仅支持和 v-model
配套使用。这里 toggle
属性的值会在选中时被设为 'yes'
,取消选择时设为 'no'
。你同样可以通过 v-bind
将其绑定为其他动态值:
<input type="checkbox" v-model="toggle" :true-value="dynamicTrueValue" :false-value="dynamicFalseValue" />
单选按钮
<input type="radio" v-model="pick" :value="first" />
<input type="radio" v-model="pick" :value="second" />
pick
会在第一个按钮选中时被设为 first
,在第二个按钮选中时被设为 second
。
选择器选项
<select v-model="selected">
<!-- 内联对象字面量 -->
<option :value="{ number: 123 }">123</option>
</select>
v-model
同样也支持非字符串类型的值绑定!在上面这个例子中,当某个选项被选中,selected
会被设为该对象字面量值 { number: 123 }
。
修饰符:
.lazy
默认情况下,v-model
会在每次 input
事件后更新数据 (IME 拼字阶段的状态例外)。你可以添加 lazy
修饰符来改为在每次 change
事件后更新数据:
<!-- 在 "change" 事件后同步更新而不是 "input" -->
<input v-model.lazy="msg" />
.number
如果你想让用户输入自动转换为数字,你可以在 v-model
后添加 .number
修饰符来管理输入:
<input v-model.number="age" />
如果该值无法被 parseFloat()
处理,那么将返回原始值。
number
修饰符会在输入框有 type="number"
时自动启用。
.trim
如果你想要默认自动去除用户输入内容中两端的空格,你可以在 v-model
后添加 .trim
修饰符:
<input v-model.trim="msg" />
组件上的 v-model
HTML 的内置表单输入类型并不总能满足所有需求。幸运的是,我们可以使用 Vue 构建具有自定义行为的可复用输入组件,并且这些输入组件也支持 v-model
!要了解更多关于此的内容,请在组件指引中阅读配合 v-model 使用。