【Vue】入门基础

在这里插入图片描述

个人主页:Guiat
归属专栏:Vue

在这里插入图片描述

正文

1. Vue简介

Vue.js是一个用于构建用户界面的渐进式JavaScript框架。与其他大型框架不同的是,Vue被设计为可以自底向上逐层应用。Vue的核心库只关注视图层,易于上手,便于与第三方库或既有项目整合。

1.1 Vue的特点

  • 响应式系统:自动追踪依赖关系并更新DOM
  • 组件化开发:可复用的组件系统
  • 虚拟DOM:高效的DOM操作
  • 轻量级:压缩后大小约33KB
  • 易学易用:上手快,文档完善

1.2 Vue的发展历程

  • Vue 1.0:2015年发布
  • Vue 2.0:2016年发布,重写了响应式系统
  • Vue 3.0:2020年发布,使用Proxy重写响应式系统,提供Composition API

2. 安装与使用

2.1 直接引入

<!-- 开发环境版本 -->
<script src="https://cdn.jsdelivr.net/npm/vue@3/dist/vue.global.js"></script>

<!-- 生产环境版本 -->
<script src="https://cdn.jsdelivr.net/npm/vue@3/dist/vue.global.prod.js"></script>

2.2 使用npm安装

# 最新稳定版
npm install vue@next

2.3 使用Vue CLI

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

# 创建项目
vue create my-project

3. Vue基础语法

3.1 创建Vue实例

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

app.mount('#app')
<div id="app">
  {{ message }}
</div>

3.2 数据绑定

3.2.1 文本插值

<span>{{ message }}</span>

3.2.2 HTML属性绑定

<div v-bind:id="dynamicId"></div>
<!-- 简写 -->
<div :id="dynamicId"></div>

3.3 条件渲染

<div v-if="seen">现在你看到我了</div>
<div v-else-if="condition">条件成立时显示</div>
<div v-else>否则显示我</div>

<!-- v-show只是切换元素的CSS display属性 -->
<div v-show="seen">使用v-show的元素始终会被渲染</div>

3.4 列表渲染

<ul>
  <li v-for="(item, index) in items" :key="item.id">
    {{ index }} - {{ item.text }}
  </li>
</ul>
data() {
  return {
    items: [
      { id: 1, text: '学习 JavaScript' },
      { id: 2, text: '学习 Vue' },
      { id: 3, text: '整个牛项目' }
    ]
  }
}

4. 事件处理

4.1 监听事件

<button v-on:click="counter += 1">增加 1</button>
<!-- 简写 -->
<button @click="counter += 1">增加 1</button>

4.2 方法事件处理器

<button @click="greet">打招呼</button>
data() {
  return {
    name: '张三'
  }
},
methods: {
  greet() {
    alert('Hello ' + this.name + '!')
  }
}

4.3 事件修饰符

<!-- 阻止单击事件继续传播 -->
<a @click.stop="doThis"></a>

<!-- 提交事件不再重载页面 -->
<form @submit.prevent="onSubmit"></form>

<!-- 修饰符可以串联 -->
<a @click.stop.prevent="doThat"></a>

<!-- 只有在 event.target 是元素本身时才触发处理函数 -->
<div @click.self="doThat">...</div>

5. 表单输入绑定

5.1 基础用法

<input v-model="message" placeholder="编辑我...">
<p>消息是: {{ message }}</p>

5.2 不同输入类型

<!-- 文本 -->
<input v-model="message">

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

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

<!-- 单选按钮 -->
<input type="radio" value="One" v-model="picked">
<input type="radio" value="Two" v-model="picked">

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

6. 组件基础

6.1 组件注册

// 全局注册
const app = Vue.createApp({})
app.component('my-component', {
  template: '<div>组件内容</div>'
})

// 局部注册
const ComponentA = {
  template: '<div>组件A</div>'
}

const app = Vue.createApp({
  components: {
    'component-a': ComponentA
  }
})

6.2 组件通信

6.2.1 Props向下传递

// 子组件
app.component('blog-post', {
  props: ['title'],
  template: '<h3>{{ title }}</h3>'
})
<!-- 父组件使用 -->
<blog-post title="Vue学习笔记"></blog-post>

6.2.2 事件向上传递

// 子组件
app.component('button-counter', {
  template: `
    <button @click="incrementCounter">
      点击了 {{ count }} 次
    </button>
  `,
  data() {
    return {
      count: 0
    }
  },
  methods: {
    incrementCounter() {
      this.count++
      this.$emit('increment')
    }
  }
})
<!-- 父组件监听事件 -->
<button-counter @increment="total++"></button-counter>

7. Vue生命周期

7.1 生命周期钩子

const app = Vue.createApp({
  data() {
    return {
      message: 'Hello'
    }
  },
  beforeCreate() {
    console.log('beforeCreate')
  },
  created() {
    console.log('created')
  },
  beforeMount() {
    console.log('beforeMount')
  },
  mounted() {
    console.log('mounted')
  },
  beforeUpdate() {
    console.log('beforeUpdate')
  },
  updated() {
    console.log('updated')
  },
  beforeUnmount() {
    console.log('beforeUnmount')
  },
  unmounted() {
    console.log('unmounted')
  }
})

7.2 生命周期图示

Vue生命周期图示

Vue实例从创建到销毁的整个过程被称为生命周期。Vue提供了多个生命周期钩子函数,让开发者可以在特定阶段添加自己的代码。以下是Vue生命周期的详细图示:

创建阶段 → 挂载阶段 → 更新阶段 → 卸载阶段

Vue 3生命周期图示

beforeCreate  → created → beforeMount → mounted → beforeUpdate → updated → beforeUnmount → unmounted
     ↓             ↓           ↓            ↓           ↓             ↓           ↓              ↓
初始化事件和生命周期  → 初始化注入和响应式  → 创建DOM  → 挂载DOM  → 虚拟DOM重新渲染 → 更新DOM → 移除事件监听器 → 销毁组件实例

生命周期钩子详解

  1. beforeCreate: 实例初始化之后,数据观测和事件配置之前被调用

    • 此时无法访问data和methods
  2. created: 实例创建完成后被调用

    • 可以访问data和methods
    • 还未挂载DOM,无法访问$el
  3. beforeMount: 挂载开始之前被调用

    • 模板已编译,但还未渲染到页面
  4. mounted: 挂载完成后调用

    • 可以访问DOM元素
    • 适合执行DOM操作和发送API请求
  5. beforeUpdate: 数据更新时,DOM更新之前调用

    • 可以在DOM更新前访问现有DOM
  6. updated: DOM更新完成后调用

    • 避免在此钩子中更改状态,可能导致无限循环
  7. beforeUnmount: 组件卸载前调用

    • 实例仍然可用
  8. unmounted: 组件卸载后调用

    • 所有子组件也已卸载
    • 所有响应式效果已停止

Vue 2与Vue 3生命周期对比

Vue 2Vue 3描述
beforeCreatebeforeCreate实例初始化之前
createdcreated实例创建完成
beforeMountbeforeMountDOM挂载前
mountedmountedDOM挂载后
beforeUpdatebeforeUpdate数据更新前
updatedupdated数据更新后
beforeDestroybeforeUnmount实例销毁前
destroyedunmounted实例销毁后

Composition API中的生命周期钩子

Vue 3的Composition API提供了等效的生命周期钩子函数:

import { 
  onBeforeMount, 
  onMounted,
  onBeforeUpdate,
  onUpdated,
  onBeforeUnmount,
  onUnmounted
} from 'vue'

export default {
  setup() {
    // beforeCreate和created钩子在setup函数本身内部
    console.log('setup - 相当于beforeCreate和created')
    
    onBeforeMount(() => {
      console.log('onBeforeMount')
    })
    
    onMounted(() => {
      console.log('onMounted')
    })
    
    onBeforeUpdate(() => {
      console.log('onBeforeUpdate')
    })
    
    onUpdated(() => {
      console.log('onUpdated')
    })
    
    onBeforeUnmount(() => {
      console.log('onBeforeUnmount')
    })
    
    onUnmounted(() => {
      console.log('onUnmounted')
    })
  }
}

8. Vue Router基础

8.1 安装

npm install vue-router@4

8.2 基本配置

// router/index.js
import { createRouter, createWebHistory } from 'vue-router'
import Home from '../views/Home.vue'
import About from '../views/About.vue'

const routes = [
  {
    path: '/',
    name: 'Home',
    component: Home
  },
  {
    path: '/about',
    name: 'About',
    component: About
  }
]

const router = createRouter({
  history: createWebHistory(),
  routes
})

export default router
// main.js
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'

const app = createApp(App)
app.use(router)
app.mount('#app')

8.3 路由导航

<router-link to="/">首页</router-link>
<router-link to="/about">关于</router-link>

<!-- 路由出口 -->
<router-view></router-view>

9. Vuex状态管理

9.1 安装

npm install vuex@next

9.2 基本配置

// store/index.js
import { createStore } from 'vuex'

export default createStore({
  state: {
    count: 0
  },
  mutations: {
    increment(state) {
      state.count++
    }
  },
  actions: {
    incrementAsync({ commit }) {
      setTimeout(() => {
        commit('increment')
      }, 1000)
    }
  },
  getters: {
    doubleCount(state) {
      return state.count * 2
    }
  }
})
// main.js
import { createApp } from 'vue'
import App from './App.vue'
import store from './store'

const app = createApp(App)
app.use(store)
app.mount('#app')

9.3 在组件中使用

<template>
  <div>
    <p>Count: {{ count }}</p>
    <p>Double Count: {{ doubleCount }}</p>
    <button @click="increment">+1</button>
    <button @click="incrementAsync">Async +1</button>
  </div>
</template>

<script>
import { mapState, mapGetters, mapMutations, mapActions } from 'vuex'

export default {
  computed: {
    ...mapState(['count']),
    ...mapGetters(['doubleCount'])
  },
  methods: {
    ...mapMutations(['increment']),
    ...mapActions(['incrementAsync'])
  }
}
</script>

10. Composition API

10.1 基本用法

<template>
  <div>
    <p>Count: {{ count }}</p>
    <button @click="increment">+1</button>
  </div>
</template>

<script>
import { ref, onMounted } from 'vue'

export default {
  setup() {
    // 响应式状态
    const count = ref(0)
    
    // 方法
    function increment() {
      count.value++
    }
    
    // 生命周期钩子
    onMounted(() => {
      console.log('组件已挂载')
    })
    
    // 返回需要暴露给模板的内容
    return {
      count,
      increment
    }
  }
}
</script>

10.2 响应式API

import { ref, reactive, computed, watch } from 'vue'

// ref: 适用于基本类型
const count = ref(0)
console.log(count.value) // 0

// reactive: 适用于对象
const state = reactive({
  count: 0,
  name: 'Vue'
})
console.log(state.count) // 0

// computed: 计算属性
const doubleCount = computed(() => count.value * 2)

// watch: 侦听变化
watch(count, (newValue, oldValue) => {
  console.log(`count从${oldValue}变为${newValue}`)
})

11. 实战项目:待办事项应用

11.1 项目结构

todo-app/
├── public/
│   └── index.html
└── src/
    ├── assets/
    ├── components/
    │   ├── TodoForm.vue
    │   ├── TodoItem.vue
    │   └── TodoList.vue
    ├── App.vue
    └── main.js

11.2 组件实现

<!-- App.vue -->
<template>
  <div class="container">
    <h1>Vue待办事项</h1>
    <todo-form @add-todo="addTodo"></todo-form>
    <todo-list 
      :todos="todos" 
      @toggle-todo="toggleTodo"
      @delete-todo="deleteTodo"
    ></todo-list>
  </div>
</template>

<script>
import TodoForm from './components/TodoForm.vue'
import TodoList from './components/TodoList.vue'

export default {
  components: {
    TodoForm,
    TodoList
  },
  data() {
    return {
      todos: [
        { id: 1, text: '学习Vue基础', completed: true },
        { id: 2, text: '完成待办事项应用', completed: false }
      ]
    }
  },
  methods: {
    addTodo(text) {
      this.todos.push({
        id: Date.now(),
        text,
        completed: false
      })
    },
    toggleTodo(id) {
      const todo = this.todos.find(todo => todo.id === id)
      if (todo) {
        todo.completed = !todo.completed
      }
    },
    deleteTodo(id) {
      this.todos = this.todos.filter(todo => todo.id !== id)
    }
  }
}
</script>
<!-- TodoForm.vue -->
<template>
  <form @submit.prevent="handleSubmit">
    <input 
      v-model="newTodo" 
      placeholder="添加新待办..."
      required
    >
    <button type="submit">添加</button>
  </form>
</template>

<script>
export default {
  data() {
    return {
      newTodo: ''
    }
  },
  methods: {
    handleSubmit() {
      if (this.newTodo.trim()) {
        this.$emit('add-todo', this.newTodo.trim())
        this.newTodo = ''
      }
    }
  }
}
</script>
<!-- TodoList.vue -->
<template>
  <ul class="todo-list">
    <todo-item
      v-for="todo in todos"
      :key="todo.id"
      :todo="todo"
      @toggle="$emit('toggle-todo', todo.id)"
      @delete="$emit('delete-todo', todo.id)"
    ></todo-item>
  </ul>
</template>

<script>
import TodoItem from './TodoItem.vue'

export default {
  components: {
    TodoItem
  },
  props: {
    todos: {
      type: Array,
      required: true
    }
  }
}
</script>
<!-- TodoItem.vue -->
<template>
  <li :class="{ completed: todo.completed }">
    <input 
      type="checkbox" 
      :checked="todo.completed"
      @change="$emit('toggle')"
    >
    <span>{{ todo.text }}</span>
    <button @click="$emit('delete')">删除</button>
  </li>
</template>

<script>
export default {
  props: {
    todo: {
      type: Object,
      required: true
    }
  }
}
</script>

<style scoped>
.completed {
  text-decoration: line-through;
  color: gray;
}
</style>

12. 性能优化

12.1 优化策略

  1. 使用key:在v-for中始终使用key
  2. 避免过度监听:合理使用computed和watch
  3. 懒加载组件:使用动态导入
  4. 保持数据简单:避免过深的响应式对象嵌套
  5. 虚拟滚动:处理大列表

12.2 代码分割

// 路由懒加载
const routes = [
  {
    path: '/about',
    name: 'About',
    component: () => import('../views/About.vue')
  }
]

12.3 性能分析工具

  • Vue Devtools
  • Chrome Performance面板
  • Lighthouse

13. Vue 3新特性总结

13.1 主要变化

  1. Composition API:更好的代码组织和逻辑复用
  2. Teleport:将内容渲染到DOM树的其他位置
  3. Fragments:组件可以有多个根节点
  4. Suspense:处理异步组件
  5. 更好的TypeScript支持:类型推断改进

13.2 性能提升

  • 更小的包体积
  • 更快的渲染速度
  • 更低的内存占用

结语
感谢您的阅读!期待您的一键三连!欢迎指正!

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

【Air】

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值