选项式基础语法
Vue 基础语法详解与示例
Vue.js 是一个用于构建用户界面的渐进式 JavaScript 框架,采用组件化架构,使代码可复用且易于维护。下面将详细介绍 Vue 的核心语法和特性,并提供丰富示例。
一、Vue 实例与响应式原理
1. 创建 Vue 实例
每个 Vue 应用从创建根实例开始,通过 new Vue() 构造函数初始化。
const app = new Vue({
// 挂载点:Vue 实例控制的 DOM 元素
el: '#app',
// 数据对象:响应式数据
data() {
return {
message: 'Hello Vue!',
count: 0,
user: {
name: 'John',
age: 30
}
}
},
// 计算属性:基于依赖缓存的动态属性
computed: {
reversedMessage() {
return this.message.split('').reverse().join('');
}
},
// 方法:事件处理和自定义逻辑
methods: {
increment() {
this.count++;
}
},
// 监听器:观察数据变化并执行副作用
watch: {
count(newVal, oldVal) {
console.log(`Count changed from ${oldVal} to ${newVal}`);
}
}
});
2. 响应式原理
Vue 通过 Object.defineProperty() 实现数据劫持,当数据变化时自动更新 DOM。
// 以下代码模拟 Vue 的响应式原理
function defineReactive(obj, key, val) {
Object.defineProperty(obj, key, {
get() {
console.log(`Getting key "${key}": ${val}`);
return val;
},
set(newVal) {
if (val !== newVal) {
console.log(`Setting key "${key}" to: ${newVal}`);
val = newVal;
updateDOM(); // Vue 实际通过发布-订阅模式通知更新
}
}
});
}
function updateDOM() {
// 实际 Vue 会通过虚拟 DOM 高效更新
console.log('DOM updated');
}
二、模板语法与指令
1. 插值表达式
使用 {{ }} 进行文本插值,支持 JavaScript 表达式。
<div id="app">
<!-- 基本文本插值 -->
<p>{{ message }}</p>
<!-- 表达式计算 -->
<p>{{ 1 + 1 }}</p>
<!-- 三元表达式 -->
<p>{{ isLoading ? 'Loading...' : 'Loaded' }}</p>
<!-- 调用方法 -->
<p>{{ getFullName() }}</p>
</div>
2. 指令详解
指令是带有 v- 前缀的特殊属性,用于实现特殊功能。
<!-- 条件渲染 -->
<p v-if="status === 'success'">操作成功</p>
<p v-else-if="status === 'loading'">加载中...</p>
<p v-else>操作失败</p>
<!-- 列表渲染 -->
<ul>
<li v-for="(item, index) in items" :key="item.id">
{{ index }}. {{ item.name }}
</li>
</ul>
<!-- 事件绑定 -->
<button v-on:click="handleClick">点击我</button>
<button @click="handleClick">简写语法</button>
<!-- 事件修饰符 -->
<form @submit.prevent="submitForm">
<input type="text">
</form>
<!-- 属性绑定 -->
<img :src="imageUrl" :alt="imageAlt">
<button :disabled="isDisabled">按钮</button>
<!-- 双向数据绑定 -->
<input v-model="message" type="text">
<!-- 类与样式绑定 -->
<div :class="{ active: isActive }"></div>
<div :style="{ color: textColor, fontSize: fontSize + 'px' }"></div>
三、组件系统
1. 全局组件注册
// 注册全局组件
Vue.component('todo-item', {
// 组件选项
props: ['todo'],
template: `
<li>
{{ todo.text }}
<button @click="$emit('remove')">删除</button>
</li>
`
});
// 在父组件模板中使用
<todo-item v-for="item in todos" :todo="item" @remove="removeTodo"></todo-item>
2. 局部组件注册
const ChildComponent = {
template: '<div>子组件</div>'
};
new Vue({
components: {
'child-component': ChildComponent
},
template: '<child-component></child-component>'
});
3. 组件通信
- props 向下传递:父组件 → 子组件
- 事件向上传递:子组件 → 父组件
// 父组件
new Vue({
data() {
return {
parentMsg: '来自父组件的消息'
}
},
methods: {
handleChildEvent(msg) {
console.log('接收到子组件消息:', msg);
}
},
template: `
<child-component
:parent-message="parentMsg"
@child-event="handleChildEvent"
></child-component>
`
});
// 子组件
const ChildComponent = {
props: ['parentMessage'],
methods: {
sendToParent() {
this.$emit('child-event', '来自子组件的消息');
}
},
template: `
<div>
<p>父组件消息: {{ parentMessage }}</p>
<button @click="sendToParent">发送消息给父组件</button>
</div>
`
};
四、生命周期钩子
Vue 实例从创建到销毁的整个过程称为生命周期,包含多个钩子函数。
new Vue({
data() {
return {
items: []
}
},
beforeCreate() {
// 实例初始化后,数据观测和 event/watcher 事件配置之前被调用
console.log('beforeCreate');
},
created() {
// 实例已经创建完成之后被调用
// 此时 data、methods 已可用
console.log('created');
this.fetchData();
},
beforeMount() {
// 挂载开始之前被调用
console.log('beforeMount');
},
mounted() {
// 挂载完成后调用
// 此时 el 已渲染为真实 DOM
console.log('mounted');
this.$el.querySelector('h1').textContent = '已挂载';
},
beforeUpdate() {
// 数据更新前调用
console.log('beforeUpdate');
},
updated() {
// 数据更新导致的 DOM 重新渲染后调用
console.log('updated');
},
beforeDestroy() {
// 实例销毁之前调用
console.log('beforeDestroy');
},
destroyed() {
// 实例销毁后调用
console.log('destroyed');
},
methods: {
fetchData() {
// 模拟异步数据获取
setTimeout(() => {
this.items = [1, 2, 3];
}, 1000);
}
}
});
五、计算属性与监听器
1. 计算属性
计算属性基于依赖缓存,只有依赖变化时才会重新计算。
new Vue({
data() {
return {
firstName: 'John',
lastName: 'Doe'
}
},
computed: {
// 计算属性的 getter
fullName() {
return `${this.firstName} ${this.lastName}`;
},
// 计算属性的 setter
fullName: {
get() {
return `${this.firstName} ${this.lastName}`;
},
set(newValue) {
const names = newValue.split(' ');
this.firstName = names[0];
this.lastName = names[names.length - 1];
}
}
}
});
2. 监听器
当需要监听数据变化并执行异步或开销较大的操作时使用。
new Vue({
data() {
return {
question: '',
answer: '请先提出你的问题...'
}
},
watch: {
// 监听 question 变化
question(newQuestion) {
if (newQuestion.includes('?')) {
this.getAnswer();
}
}
},
methods: {
getAnswer() {
// 模拟 API 请求
setTimeout(() => {
this.answer = '也许吧,我还不确定';
}, 1000);
}
}
});
六、表单输入绑定
v-model 指令在表单控件上创建双向数据绑定,会根据控件类型自动处理数据。
<!-- 文本 -->
<input v-model="message" placeholder="输入文本">
<!-- 多行文本 -->
<textarea v-model="message"></textarea>
<!-- 复选框(单个) -->
<input type="checkbox" id="agree" v-model="isAgreed">
<label for="agree">{{ isAgreed ? '已同意' : '未同意' }}</label>
<!-- 复选框(多个) -->
<input type="checkbox" id="apple" value="apple" v-model="selectedFruits">
<label for="apple">苹果</label>
<input type="checkbox" id="banana" value="banana" v-model="selectedFruits">
<label for="banana">香蕉</label>
<!-- 单选按钮 -->
<input type="radio" id="male" value="male" v-model="gender">
<label for="male">男</label>
<input type="radio" id="female" value="female" v-model="gender">
<label for="female">女</label>
<!-- 选择框(单选) -->
<select v-model="selected">
<option value="">请选择</option>
<option value="A">选项A</option>
<option value="B">选项B</option>
</select>
<!-- 选择框(多选) -->
<select v-model="selectedOptions" multiple>
<option value="A">选项A</option>
<option value="B">选项B</option>
<option value="C">选项C</option>
</select>
修饰符
.lazy:取代input事件,使用change事件.number:自动将输入转换为数字类型.trim:自动过滤输入的首尾空格
七、Vue Router 基础
Vue Router 是 Vue.js 官方的路由管理器,用于实现单页面应用的路由功能。
1. 基本路由配置
// 1. 定义路由组件
const Home = { template: '<div>Home Page</div>' };
const About = { template: '<div>About Page</div>' };
const User = {
props: ['id'],
template: '<div>User {{ id }}</div>'
};
// 2. 定义路由
const routes = [
{ path: '/', component: Home },
{ path: '/about', component: About },
{ path: '/user/:id', component: User, props: true }
];
// 3. 创建 router 实例
const router = new VueRouter({
routes,
mode: 'history' // 使用 HTML5 History 模式
});
// 4. 创建和挂载根实例
new Vue({
router
}).$mount('#app');
2. 路由导航
<!-- 使用 router-link 组件进行导航 -->
<router-link to="/">Home</router-link>
<router-link to="/about">About</router-link>
<router-link :to="{ name: 'user', params: { id: 123 }}">User 123</router-link>
<!-- 路由出口,匹配的组件将渲染在这里 -->
<router-view></router-view>
八、Vuex 状态管理(基础)
Vuex 是专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。
1. 基本概念
// 创建 store
import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex);
const store = new Vuex.Store({
// 状态:应用的数据源
state: {
count: 0
},
// getters:类似于计算属性,用于获取状态的派生值
getters: {
doubleCount(state) {
return state.count * 2;
}
},
// mutations:更改状态的唯一方法是提交 mutation
mutations: {
increment(state) {
state.count++;
},
incrementBy(state, payload) {
state.count += payload.amount;
}
},
// actions:处理异步操作,提交 mutations
actions: {
incrementAsync(context) {
setTimeout(() => {
context.commit('increment');
}, 1000);
},
incrementByAsync({ commit }, payload) {
return new Promise((resolve) => {
setTimeout(() => {
commit('incrementBy', payload);
resolve();
}, 1000);
});
}
}
});
2. 在组件中使用 Vuex
// 在组件中获取状态
export default {
computed: {
count() {
return this.$store.state.count;
},
doubleCount() {
return this.$store.getters.doubleCount;
}
},
methods: {
increment() {
// 提交 mutation
this.$store.commit('increment');
},
incrementAsync() {
// 分发 action
this.$store.dispatch('incrementAsync');
}
}
};