Appearance
Vue.js 基础语法
Vue.js 提供了一套简洁的模板语法,让开发者能够以声明式的方式将数据渲染到DOM中。
模板语法
插值
Vue.js 使用 双大括号语法进行文本插值:
vue
<template>
<div>
<!-- 文本插值 -->
<p>{{ message }}</p>
<!-- 使用JavaScript表达式 -->
<p>{{ message + '!' }}</p>
<p>{{ count > 10 ? '大于10' : '小于等于10' }}</p>
<p>{{ user.firstName + ' ' + user.lastName }}</p>
</div>
</template>
<script>
export default {
data() {
return {
message: 'Hello Vue!',
count: 5,
user: {
firstName: 'John',
lastName: 'Doe'
}
}
}
}
</script>
指令
指令是带有 v- 前缀的特殊属性,用于在表达式的值改变时响应式地作用于DOM:
vue
<template>
<div>
<!-- v-text: 更新元素的文本内容 -->
<p v-text="message"></p>
<!-- v-html: 更新元素的innerHTML -->
<div v-html="rawHtml"></div>
<!-- v-show: 条件显示 -->
<p v-show="isVisible">这是一段条件显示的文本</p>
<!-- v-if/v-else/v-else-if: 条件渲染 -->
<div v-if="type === 'A'">A</div>
<div v-else-if="type === 'B'">B</div>
<div v-else>C</div>
<!-- v-for: 列表渲染 -->
<ul>
<li v-for="item in items" :key="item.id">
{{ item.name }}
</li>
</ul>
<!-- v-bind: 动态绑定属性 -->
<img v-bind:src="imageSrc" :alt="imageAlt">
<button :disabled="isDisabled">按钮</button>
<!-- v-on: 事件监听 -->
<button v-on:click="handleClick">点击</button>
<button @click="handleClick">点击</button> <!-- @ 是 v-on: 的缩写 -->
<!-- v-model: 双向数据绑定 -->
<input v-model="inputValue">
<textarea v-model="textareaValue"></textarea>
</div>
</template>
<script>
export default {
data() {
return {
message: 'Hello Vue!',
rawHtml: '<span style="color: red">红色文本</span>',
isVisible: true,
type: 'A',
items: [
{ id: 1, name: '苹果' },
{ id: 2, name: '香蕉' },
{ id: 3, name: '橙子' }
],
imageSrc: '/path/to/image.jpg',
imageAlt: '图片描述',
isDisabled: false,
inputValue: '',
textareaValue: ''
}
},
methods: {
handleClick() {
console.log('按钮被点击了!');
}
}
}
</script>
计算属性和侦听器
计算属性
计算属性是基于响应式依赖进行缓存的,只有依赖发生改变时才会重新计算:
vue
<template>
<div>
<p>原始消息: {{ message }}</p>
<p>反转消息: {{ reversedMessage }}</p>
<p>反转消息(方法): {{ reverseMessage() }}</p>
</div>
</template>
<script>
export default {
data() {
return {
message: 'Hello Vue!'
}
},
computed: {
// 计算属性
reversedMessage() {
return this.message.split('').reverse().join('')
}
},
methods: {
// 方法(每次渲染都会执行)
reverseMessage() {
return this.message.split('').reverse().join('')
}
}
}
</script>
侦听器
当需要在数据变化时执行异步或开销较大的操作时,侦听器很有用:
vue
<template>
<div>
<p>问一个问题是(Yes/No):</p>
<p>{{ question }}</p>
<input v-model="question" @input="debouncedGetAnswer">
</div>
</template>
<script>
import _ from 'lodash'
export default {
data() {
return {
question: '',
answer: '问题以 ? 结尾时我会给你答案'
}
},
watch: {
// 侦听 question 的变化
question(newQuestion, oldQuestion) {
this.answer = '正在思考...'
this.getAnswer()
}
},
created() {
// 使用lodash的防抖功能
this.debouncedGetAnswer = _.debounce(this.getAnswer, 500)
},
methods: {
async getAnswer() {
if (this.question.indexOf('?') === -1) {
this.answer = '问题以 ? 结尾时我会给你答案'
return
}
this.answer = '正在思考...'
try {
const res = await fetch('https://yesno.wtf/api')
this.answer = (await res.json()).answer
} catch (error) {
this.answer = '无法获取答案,请稍后重试'
}
}
}
}
</script>
条件渲染
v-if vs v-show
vue
<template>
<div>
<!-- v-if: 条件渲染,完全销毁/创建DOM元素 -->
<h1 v-if="awesome">Vue很awesome!</h1>
<!-- v-show: 条件显示,通过CSS切换显示/隐藏 -->
<h1 v-show="awesome">Vue很awesome!</h1>
<!-- v-if, v-else-if, v-else -->
<div v-if="type === 'A'">
A
</div>
<div v-else-if="type === 'B'">
B
</div>
<div v-else>
Not A/B
</div>
</div>
</template>
<script>
export default {
data() {
return {
awesome: true,
type: 'A'
}
}
}
</script>
列表渲染
v-for 基础用法
vue
<template>
<div>
<!-- 遍历数组 -->
<ul>
<li v-for="item in items" :key="item.id">
{{ item.name }} - {{ item.price }}
</li>
</ul>
<!-- 使用索引 -->
<ul>
<li v-for="(item, index) in items" :key="item.id">
{{ index }} - {{ item.name }}
</li>
</ul>
<!-- 遍历对象 -->
<ul>
<li v-for="(value, key) in object" :key="key">
{{ key }}: {{ value }}
</li>
</ul>
<!-- 遍历数字 -->
<span v-for="n in 10" :key="n">{{ n }} </span>
</div>
</template>
<script>
export default {
data() {
return {
items: [
{ id: 1, name: '苹果', price: 5 },
{ id: 2, name: '香蕉', price: 3 },
{ id: 3, name: '橙子', price: 4 }
],
object: {
name: 'John',
age: 30,
city: 'New York'
}
}
}
}
</script>
事件处理
事件修饰符
vue
<template>
<div>
<!-- 普通事件 -->
<button @click="counter++">计数器: {{ counter }}</button>
<!-- 事件修饰符 -->
<!-- .stop - 阻止事件冒泡 -->
<div @click="outerClick">
外层
<button @click.stop="innerClick">内层 - 不会冒泡</button>
</div>
<!-- .prevent - 阻止默认行为 -->
<form @submit.prevent="onSubmit">
<input type="text" v-model="inputValue">
<button type="submit">提交</button>
</form>
<!-- .capture - 使用事件捕获模式 -->
<div @click.capture="captureClick">
捕获模式
<button @click="normalClick">普通点击</button>
</div>
<!-- .self - 只在事件目标是元素本身时触发 -->
<div @click.self="selfClick">
只在点击自身时触发
<button @click="buttonClick">按钮</button>
</div>
<!-- .once - 事件只触发一次 -->
<button @click.once="onceClick">只触发一次</button>
<!-- 按键修饰符 -->
<input @keyup.enter="onEnter" @keyup.esc="onEscape">
<!-- 系统修饰键 -->
<div @click.ctrl="ctrlClick">按住Ctrl点击</div>
</div>
</template>
<script>
export default {
data() {
return {
counter: 0,
inputValue: ''
}
},
methods: {
outerClick() {
console.log('外层点击')
},
innerClick() {
console.log('内层点击')
},
onSubmit() {
console.log('表单提交被阻止')
},
captureClick() {
console.log('捕获阶段触发')
},
normalClick() {
console.log('普通点击')
},
selfClick() {
console.log('只在点击自身时触发')
},
buttonClick() {
console.log('按钮点击')
},
onceClick() {
console.log('只触发一次')
},
onEnter() {
console.log('按下了Enter键')
},
onEscape() {
console.log('按下了Escape键')
},
ctrlClick() {
console.log('按住Ctrl点击')
}
}
}
</script>
表单输入绑定
v-model 基础用法
vue
<template>
<div>
<!-- 文本输入 -->
<input v-model="message" placeholder="输入一些文字">
<p>消息: {{ message }}</p>
<!-- 多行文本 -->
<textarea v-model="textareaValue" placeholder="多行文本"></textarea>
<p>多行文本: {{ textareaValue }}</p>
<!-- 复选框 -->
<input type="checkbox" id="checkbox" v-model="checked">
<label for="checkbox">{{ checked ? '已选中' : '未选中' }}</label>
<!-- 多个复选框 -->
<div>
<input type="checkbox" id="jack" value="Jack" v-model="checkedNames">
<label for="jack">Jack</label>
<input type="checkbox" id="john" value="John" v-model="checkedNames">
<label for="john">John</label>
<input type="checkbox" id="mike" value="Mike" v-model="checkedNames">
<label for="mike">Mike</label>
<br>
<span>选中: {{ checkedNames }}</span>
</div>
<!-- 单选按钮 -->
<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>
<br>
<span>选中: {{ picked }}</span>
</div>
<!-- 选择框 -->
<select v-model="selected">
<option disabled value="">请选择</option>
<option>A</option>
<option>B</option>
<option>C</option>
</select>
<span>选中: {{ selected }}</span>
<!-- 多选选择框 -->
<select v-model="multiSelected" multiple>
<option>A</option>
<option>B</option>
<option>C</option>
</select>
<span>选中: {{ multiSelected }}</span>
</div>
</template>
<script>
export default {
data() {
return {
message: '',
textareaValue: '',
checked: false,
checkedNames: [],
picked: '',
selected: '',
multiSelected: []
}
}
}
</script>
组件基础
组件注册和使用
vue
<!-- MyButton.vue -->
<template>
<button class="my-button" @click="handleClick">
<slot></slot>
</button>
</template>
<script>
export default {
name: 'MyButton',
methods: {
handleClick() {
this.$emit('click')
}
}
}
</script>
<style scoped>
.my-button {
padding: 8px 16px;
background-color: #007bff;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
}
</style>
vue
<!-- 父组件 -->
<template>
<div>
<MyButton @click="onButtonClick">点击我</MyButton>
</div>
</template>
<script>
import MyButton from './MyButton.vue'
export default {
components: {
MyButton
},
methods: {
onButtonClick() {
console.log('按钮被点击了!')
}
}
}
</script>
Vue.js的语法简洁而强大,通过这些基础语法,开发者可以构建出功能丰富的交互式界面。