Vue 学习指南

本指南包含 Vue 的核心概念、详细注释和实例代码,帮助您快速学习 Vue 技术。

1. Vue 简介

1.1 什么是 Vue?

Vue 是一个渐进式 JavaScript 框架,用于构建用户界面。它由尤雨溪创建,专注于视图层,易于上手,同时也能为复杂的单页应用提供驱动。

1.2 Vue 的优势

1.3 Vue 工作原理

// Vue 工作流程:
// 1. 创建 Vue 实例
// 2. 编译模板为渲染函数
// 3. 创建虚拟 DOM 树
// 4. 当数据变化时,生成新的虚拟 DOM 树
// 5. 通过 diff 算法比较新旧虚拟 DOM 树
// 6. 只更新变化的部分到真实 DOM
// 7. 渲染到浏览器

2. 环境搭建

2.1 使用 Vue CLI

// 安装 Vue CLI
npm install -g @vue/cli

// 创建 Vue 项目
vue create my-app

// 进入项目目录
cd my-app

// 启动开发服务器
npm run serve

2.2 使用 Vite

// 使用 Vite 创建 Vue 项目
npm create vite@latest my-app -- --template vue

// 进入项目目录
cd my-app

// 安装依赖
npm install

// 启动开发服务器
npm run dev

2.3 CDN 引入(本教程使用)

// 引入 Vue 3
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>

3. 基础语法

3.1 创建 Vue 应用

// 创建 Vue 应用
const { createApp } = Vue;

const app = createApp({
  data() {
    return {
      message: 'Hello Vue!'
    };
  }
});

app.mount('#app');

3.2 数据绑定

// 文本插值
<p>{{ message }}</p>

// 属性绑定
<img :src="imageSrc" :alt="imageAlt">

// 类绑定
<div :class="{ active: isActive }"></div>

// 样式绑定
<div :style="{ color: activeColor, fontSize: fontSize + 'px' }"></div>

3.3 指令

// v-if 条件渲染
<div v-if="seen">现在你看到我了</div>

// 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>

// v-show 条件显示
<div v-show="seen">现在你看到我了</div>

// v-for 列表渲染
<li v-for="item in items" :key="item.id">
  {{ item.text }}
</li>

// v-on 事件监听
<button v-on:click="doSomething">点击我</button>
// 简写
<button @click="doSomething">点击我</button>

// v-model 双向绑定
<input v-model="message">

实例:基础语法

消息: {{ message }}

计数: {{ count }}

现在你看到我了
现在你看不到我
  • {{ item }}

输入的内容: {{ inputValue }}

4. 计算属性和侦听器

4.1 计算属性

// 计算属性
const app = createApp({
  data() {
    return {
      firstName: '张',
      lastName: '三'
    };
  },
  computed: {
    // 计算属性:自动缓存结果
    fullName() {
      return this.firstName + ' ' + this.lastName;
    }
  }
});

// 计算属性的 setter
computed: {
  fullName: {
    get() {
      return this.firstName + ' ' + this.lastName;
    },
    set(newValue) {
      const names = newValue.split(' ');
      this.firstName = names[0];
      this.lastName = names[names.length - 1];
    }
  }
}

4.2 侦听器

// 侦听器
const app = createApp({
  data() {
    return {
      question: '',
      answer: '问题通常包含问号。;-)'
    };
  },
  watch: {
    // 侦听 question 的变化
    question(newQuestion, oldQuestion) {
      if (newQuestion.indexOf('?') > -1) {
        this.getAnswer();
      }
    }
  },
  methods: {
    getAnswer() {
      this.answer = '思考中...';
      // 模拟异步操作
      setTimeout(() => {
        this.answer = '这是一个答案!';
      }, 500);
    }
  }
});

实例:计算属性和侦听器

姓:

名:

全名: {{ fullName }}


问题:

答案: {{ answer }}

5. 组件

5.1 基本组件

// 定义组件
const MyComponent = {
  template: '<div>这是一个组件</div>'
};

// 注册组件
const app = createApp({
  components: {
    'my-component': MyComponent
  }
});

// 在模板中使用
<my-component></my-component>

5.2 组件 props

// 定义带 props 的组件
const Greeting = {
  props: ['name'],
  template: '<div>Hello, {{ name }}!</div>'
};

// 使用组件
<greeting name="张三"></greeting>

// props 验证
const Greeting = {
  props: {
    name: {
      type: String,
      required: true,
      default: '匿名'
    }
  },
  template: '<div>Hello, {{ name }}!</div>'
};

5.3 组件事件

// 子组件
const Counter = {
  data() {
    return {
      count: 0
    };
  },
  template: `
    <button @click="$emit('increment', count)">
      Increment
    </button>
  `
};

// 父组件
const app = createApp({
  components: {
    'counter': Counter
  },
  methods: {
    handleIncrement(count) {
      console.log('Incremented to:', count);
    }
  }
});

// 在模板中使用
<counter @increment="handleIncrement"></counter>

实例:组件使用

总计数: {{ totalCount }}

6. 生命周期

6.1 生命周期钩子

// Vue 3 生命周期钩子
const app = createApp({
  data() {
    return {
      message: 'Hello Vue!'
    };
  },
  // 1. 组件实例被创建后
  beforeCreate() {
    console.log('beforeCreate');
  },
  
  // 2. 实例创建完成,data 和 methods 可用
  created() {
    console.log('created');
  },
  
  // 3. 组件挂载前
  beforeMount() {
    console.log('beforeMount');
  },
  
  // 4. 组件挂载完成
  mounted() {
    console.log('mounted');
    // 在这里可以进行 DOM 操作、API 调用等
  },
  
  // 5. 组件更新前
  beforeUpdate() {
    console.log('beforeUpdate');
  },
  
  // 6. 组件更新完成
  updated() {
    console.log('updated');
  },
  
  // 7. 组件卸载前
  beforeUnmount() {
    console.log('beforeUnmount');
  },
  
  // 8. 组件卸载完成
  unmounted() {
    console.log('unmounted');
    // 在这里清理定时器、取消订阅等
  }
});

实例:生命周期

消息: {{ message }}

生命周期日志:

  • {{ log }}

7. 表单处理

7.1 基本表单绑定

// 文本输入
<input v-model="message">

// 多行文本
<textarea v-model="message"></textarea>

// 复选框
<input type="checkbox" v-model="checked">

// 多个复选框
<input type="checkbox" value="苹果" v-model="fruits">
<input type="checkbox" value="香蕉" v-model="fruits">

// 单选按钮
<input type="radio" value="男" v-model="gender"> 男
<input type="radio" value="女" v-model="gender"> 女

// 选择框
<select v-model="selected">
  <option value="">请选择</option>
  <option value="A">A</option>
  <option value="B">B</option>
</select>

// 多选选择框
<select v-model="selected" multiple>
  <option value="A">A</option>
  <option value="B">B</option>
</select>

7.2 表单修饰符

// .lazy - 在 change 事件后同步
<input v-model.lazy="message">

// .number - 自动转换为数字
<input v-model.number="age" type="number">

// .trim - 自动去除首尾空格
<input v-model.trim="message">

实例:表单处理

阅读 运动 音乐

表单数据:

{{ form }}

8. 组件通信

8.1 父子组件通信

// 父组件向子组件传递数据(props)
const Child = {
  props: ['message'],
  template: '<div>{{ message }}</div>'
};

// 子组件向父组件传递数据(events)
const Child = {
  methods: {
    handleClick() {
      this.$emit('update', '新数据');
    }
  },
  template: '<button @click="handleClick">更新数据</button>'
};

// 父组件
const Parent = {
  components: { Child },
  data() {
    return {
      parentMessage: '来自父组件的消息'
    };
  },
  methods: {
    handleUpdate(newData) {
      this.parentMessage = newData;
    }
  },
  template: `
    <div>
      <child :message="parentMessage" @update="handleUpdate"></child>
    </div>
  `
};

8.2 provide/inject

// 祖先组件提供数据
const Ancestor = {
  provide() {
    return {
      theme: 'dark'
    };
  },
  template: '<child></child>'
};

// 后代组件注入数据
const Descendant = {
  inject: ['theme'],
  template: '<div>主题: {{ theme }}</div>'
};

实例:组件通信

父组件

父组件消息: {{ parentMessage }}

9. 插槽

9.1 基本插槽

// 组件定义插槽
const MyComponent = {
  template: `
    <div>
      <slot></slot>
    </div>
  `
};

// 使用插槽
<my-component>
  <p>这是插槽内容</p>
</my-component>

9.2 具名插槽

// 组件定义具名插槽
const MyComponent = {
  template: `
    <div>
      <slot name="header"></slot>
      <slot></slot>
      <slot name="footer"></slot>
    </div>
  `
};

// 使用具名插槽
<my-component>
  <template v-slot:header>
    <h1>标题</h1>
  </template>
  <p>默认内容</p>
  <template v-slot:footer>
    <footer>页脚</footer>
  </template>
</my-component>

9.3 作用域插槽

// 组件定义作用域插槽
const MyComponent = {
  data() {
    return {
      items: ['苹果', '香蕉', '橙子']
    };
  },
  template: `
    <ul>
      <li v-for="item in items" :key="item">
        <slot :item="item" :index="index">{{ item }}</slot>
      </li>
    </ul>
  `
};

// 使用作用域插槽
<my-component>
  <template v-slot:default="{ item, index }">
    {{ index + 1 }}. {{ item }}
  </template>
</my-component>

实例:插槽使用

这是卡片的内容区域。

可以在这里放置任何内容。

10. 综合实例

10.1 待办事项应用

待办事项应用

  • {{ todo.text }}

总计: {{ todos.length }} | 已完成: {{ completedCount }} | 未完成: {{ uncompletedCount }}

11. 总结

本指南涵盖了 Vue 的核心概念和技术,包括:

通过本指南的学习,您应该能够掌握 Vue 的基本概念和核心特性,为前端开发打下坚实的基础。

Vue 是一个强大而灵活的前端框架,它通过响应式数据绑定、组件化开发和虚拟 DOM 技术,帮助开发者构建高效、可维护的用户界面。随着 Vue 3 的发布,它引入了 Composition API 等新特性,使得 Vue 更加现代化和强大。