Vue3学习:新手入门与初级教程

2024/12/28 0:03:24

本文主要是介绍Vue3学习:新手入门与初级教程,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

概述

本文全面介绍了Vue3的核心特性和开发实践,包括Vue3的新特性和与Vue2的区别,安装与配置Vue3项目的方法,以及组件化开发、响应式原理、生命周期钩子、路由与状态管理等。此外,还通过一个简单的待办事项应用案例演示了Vue3的实际应用。适合不同层次的学习者。

Vue3基础介绍

Vue3简介

Vue.js 是一个用于构建用户界面的渐进式框架。Vue3是Vue.js的最新版本,它在Vue2的基础上引入了一些新的特性和改进,以提高性能和开发体验。Vue3的核心特性包括Composition API、TypeScript支持增强、更小的体积、更好的TypeScript支持、非侵入性的依赖注入,以及更高效的渲染等。这些改进使得Vue3成为了构建现代Web应用的理想选择。

Vue3与Vue2的区别

Vue3与Vue2相比,有以下几个主要区别:

  • 响应式系统:Vue3采用了Proxy来替代Object.defineProperty作为响应式系统的基础。这使得响应式数据的变更更为高效,并支持了对数组和对象原生方法的响应。

    比如,在Vue2中,以下代码会触发重新渲染:

    // Vue2
    const state = {}
    Object.defineProperty(state, 'count', {
    get() {
      return this._count;
    },
    set(value) {
      this._count = value;
      console.log('count changed');
    }
    });
    state.count = 1;

    在Vue3中,使用Proxy:

    // Vue3
    const state = new Proxy({}, {
    set(target, key, value) {
      console.log(`${key} changed to ${value}`);
      target[key] = value;
      return true;
    }
    });
    state.count = 1;
  • Composition API:Vue3引入了Composition API,这是一个更灵活的API,允许开发者更明确地组织和重用组件逻辑。Composition API提供了setup()函数,它在组件的生命周期中可以访问组件的属性和生命周期钩子。

    比如,在Vue2中,组件逻辑分散在各个生命周期钩子中:

    // Vue2
    export default {
    data() {
      return {
        message: 'Hello Vue2'
      };
    },
    methods: {
      sayHello() {
        console.log(this.message);
      }
    }
    };

    在Vue3中,使用Composition API:

    // Vue3
    import { ref } from 'vue';
    
    export default {
    setup() {
      const message = ref('Hello Vue3');
      const sayHello = () => {
        console.log(message.value);
      };
      return {
        message,
        sayHello
      };
    }
    };
  • Teleport API:Vue3引入了Teleport API,这使得组件的内容可以在DOM树的任意位置渲染,而不仅仅限于其父节点。

    比如,使用Teleport API:

    <teleport to="body">
    <div>Content rendered in body</div>
    </teleport>
  • Fragments:Vue3支持Fragments,即一个组件可以返回多个根节点。

    比如,Vue3中可以这样返回多个根节点:

    <template>
    <div>
      <p>Paragraph 1</p>
      <p>Paragraph 2</p>
    </div>
    </template>
  • 更好的TypeScript支持:Vue3的TypeScript支持有所增强,提供了更好的类型推断和更好的工具支持。

  • 更高的性能:Vue3的渲染性能有了显著的提升,特别是在虚拟DOM优化和事件委托方面。

  • Element Update Tracker:改进的依赖跟踪系统,提高了模板解析的效率。

  • Tree-shaking支持:Vue3优化了Tree-shaking的支持,使得未使用的代码可以被完全移除,从而减小了打包后的体积。

安装与配置Vue3项目

安装Vue3

安装Vue3最简单的方法是使用Vue CLI。首先,确保你已经安装了Node.js和npm。然后,可以通过以下命令全局安装Vue CLI:

npm install -g @vue/cli

安装完Vue CLI后,你可以创建一个新的Vue3项目:

vue create my-vue3-app

在创建项目时,选择Vue 3.0预设,或者在项目设置中手动选择Vue版本为3.0。

配置项目

进入项目目录并安装依赖:

cd my-vue3-app
npm install

运行开发服务器:

npm run serve

这将启动开发服务器,并在默认浏览器中打开项目。此时,你可以开始在项目中进行开发。

Vue3组件化开发

组件的基本概念

Vue组件是可复用的Vue实例,通过组合组件可以构建出复杂的界面。组件可以有自己的数据、事件处理、生命周期等。Vue组件的定义通常包括template、script、style这三个部分,分别定义了组件的结构、逻辑和样式。

创建与使用组件

创建Vue组件的基本步骤如下:

  1. 定义组件:在Vue中定义一个组件,通常需要通过一个Vue的工厂函数,或者使用Composition API中的defineComponent

  2. 注册组件:在Vue应用中注册组件,可以通过全局注册或局部注册两种方式。

示例代码

使用defineComponent创建组件
import { defineComponent } from 'vue'

export default defineComponent({
  name: 'HelloWorld',
  props: {
    msg: String
  },
  setup(props) {
    return () => {
      return <div>{props.msg}</div>
    }
  }
})
在父组件中使用
import HelloWorld from './components/HelloWorld.vue'

export default {
  components: {
    HelloWorld
  },
  setup() {
    return {
      message: 'Hello from parent'
    }
  }
}
在模板中使用
<template>
  <div id="app">
    <HelloWorld :msg="message" />
  </div>
</template>

属性与事件的传递

在父组件和子组件之间传递数据是组件化开发的关键。父组件可以通过属性(props)向子组件传递数据,而子组件则可以通过事件(events)向父组件发送数据。

属性传递

父组件可以通过属性向子组件传递数据:

<template>
  <div>
    <ChildComponent :message="parentMessage" />
  </div>
</template>

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

export default {
  components: {
    ChildComponent
  },
  setup() {
    return {
      parentMessage: 'Hello from parent'
    }
  }
}
</script>

事件传递

子组件可以通过自定义事件向父组件发送数据:

// ChildComponent.vue
<template>
  <div>
    <button @click="sendData">Click me</button>
  </div>
</template>

<script>
export default {
  props: {
    message: String
  },
  methods: {
    sendData() {
      this.$emit('child-event', 'Hello from child')
    }
  }
}
</script>
<!-- ParentComponent.vue -->
<template>
  <div>
    <ChildComponent @child-event="handleChildEvent" />
  </div>
</template>

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

export default {
  components: {
    ChildComponent
  },
  setup() {
    const handleChildEvent = (msg) => {
      console.log(msg)
    }
    return {
      handleChildEvent
    }
  }
}
</script>

Vue3响应式原理

响应式系统概述

Vue3的响应式系统是基于ES6的Proxy对象构建的。与Vue2相比,Vue3的响应式依赖于Proxy可以更高效地追踪数据变化,支持对数组和对象原生方法的响应。此外,Vue3还优化了依赖跟踪的算法,使得在大规模数据变化时有更好的性能表现。

  • 在Vue2中,Vue使用Object.defineProperty实现响应式。比如:

    const state = {}
    Object.defineProperty(state, 'count', {
    get() {
      return this._count;
    },
    set(value) {
      this._count = value;
      console.log('count changed');
    }
    });
    state.count = 1;
  • 在Vue3中,使用Proxy实现响应式:
    const state = new Proxy({}, {
    set(target, key, value) {
      target[key] = value;
      console.log(`${key} changed to ${value}`);
      return true;
    }
    });
    state.count = 1;

ref与reactive的使用

Vue3提供了两种主要的响应式数据定义方式:refreactive。这两种方式各有特点,根据具体场景选择合适的方式可以提高开发效率和性能。

  • ref:用于包装基本值类型(如numberstring),返回一个可变的Ref对象,可以通过.value访问或修改值。

  • reactive:用于包装对象,返回一个与原对象结构一致的响应式对象,可以直接访问对象属性。

示例代码

import { ref, reactive } from 'vue'

const countRef = ref(0)
const countReactive = reactive({ count: 0 })

console.log(countRef.value)  // 输出:0
console.log(countReactive.count)  // 输出:0

countRef.value++
countReactive.count++

console.log(countRef.value)  // 输出:1
console.log(countReactive.count)  // 输出:1

响应式数据的监听与修改

Vue3提供了watchcomputed两个函数来监听响应式数据的变化和创建计算属性。

  • watch:用于监听响应式数据的变化,并在数据变化时执行回调函数。

  • computed:用于创建计算属性,根据依赖的响应式数据计算新的值。

示例代码

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

const count = ref(0)

watch(() => count.value, (newVal, oldVal) => {
  console.log(`count changed from ${oldVal} to ${newVal}`)
})

const doubleCount = computed(() => {
  return count.value * 2
})

console.log(doubleCount.value)  // 输出:0
count.value++
console.log(doubleCount.value)  // 输出:2

Vue3生命周期钩子

生命周期钩子概述

Vue组件的生命周期指的是组件从创建到销毁的整个过程中的各个阶段。每个阶段都有对应的生命周期钩子,开发者可以在这些钩子中执行特定的逻辑。Vue3的生命周期钩子与Vue2相比有一些变化,但核心概念依然保持一致。

常用生命周期钩子的使用

以下是一些常用的生命周期钩子及其用途:

  • beforeCreate:在实例初始化之前,即数据观测 (data observer) 和事件配置 (event configuration) 之前被调用。

  • created:在实例创建完成后被调用。此时实例已完成数据观测 (data observer) 和事件配置 (event configuration) 。

  • beforeMount:在挂载开始之前被调用。此时,组件实例的$el属性还不存在。

  • mounted:在组件挂载完成后被调用。此时,组件已插入DOM中。

  • beforeUnmount:在卸载组件实例之前被调用。此时,组件实例还存在,但已经从DOM中移除。

  • unmounted:在组件实例卸载后被调用。此时,组件实例已不存在。

示例代码

import { ref, onBeforeMount, onMounted, onBeforeUnmount, onUnmounted } from 'vue'

export default {
  setup() {
    const message = ref('Hello, Vue3!')

    onBeforeMount(() => {
      console.log('beforeMount')
    })

    onMounted(() => {
      console.log('mounted')
    })

    onBeforeUnmount(() => {
      console.log('beforeUnmount')
    })

    onUnmounted(() => {
      console.log('unmounted')
    })

    return {
      message
    }
  }
}

生命周期钩子的应用场景

生命周期钩子可以用于执行组件挂载后的初始化操作、数据异步加载、DOM操作等。例如,可以在mounted钩子中执行网络请求、DOM操作等。

示例代码

import { ref, onMounted } from 'vue'

export default {
  setup() {
    const message = ref('Loading...')

    onMounted(() => {
      fetch('/api/data')
        .then(response => response.json())
        .then(data => {
          message.value = data.message
        })
    })

    return {
      message
    }
  }
}

Vue3路由与状态管理

Vue Router的基本使用

Vue Router是Vue.js的官方路由管理器,它可以让应用实现基于URL的路由管理。路由配置由一个路由表定义,每个路由条目包含一个路径和对应的组件。

简单配置

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

const router = createRouter({
  history: createWebHistory(),
  routes: [
    { path: '/', component: Home },
    { path: '/about', component: About }
  ]
})

export default router

路由导航

可以在组件中使用router-linkrouter-view来导航到不同路由。

<template>
  <div>
    <router-link to="/">Home</router-link> |
    <router-link to="/about">About</router-link>
    <router-view></router-view>
  </div>
</template>
``

### Vuex的基本概念与使用

Vuex是Vue.js的状态管理库,它提供了一个集中式存储用于管理应用的所有组件中的状态。Vuex的状态以单一状态树的形式存在,每个组件可以通过`store`实例访问和更新这个状态树。

#### 安装Vuex

```bash
npm install vuex@next --save

基本使用

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

export default createStore({
  state: {
    count: 0
  },
  mutations: {
    increment(state) {
      state.count++
    }
  },
  actions: {
    increment({ commit }) {
      commit('increment')
    }
  },
  getters: {
    doubleCount: state => state.count * 2
  }
})
<!-- App.vue -->
<template>
  <div>
    <button @click="increment">Increment</button>
    {{ count }}
    {{ doubleCount }}
  </div>
</template>

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

export default {
  setup() {
    const { count, doubleCount } = mapGetters(['count', 'doubleCount'])
    const { increment } = mapActions(['increment'])

    return {
      count,
      doubleCount,
      increment
    }
  }
}
</script>
``

### 路由与状态管理的实际案例

假设我们正在开发一个简单的博客应用,其中包括文章列表和文章详情页。我们可以使用Vue Router实现导航,使用Vuex管理应用状态。

#### 路由配置

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

const router = createRouter({
  history: createWebHistory(),
  routes: [
    { path: '/', component: Home },
    { path: '/article/:id', component: Article }
  ]
})

export default router

Vuex状态管理

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

export default createStore({
  state: {
    articles: []
  },
  mutations: {
    setArticles(state, articles) {
      state.articles = articles
    }
  },
  actions: {
    fetchArticles({ commit }) {
      return fetch('/api/articles')
        .then(response => response.json())
        .then(articles => commit('setArticles', articles))
    }
  },
  getters: {
    articles: state => state.articles,
    findArticleById: state => id => state.articles.find(article => article.id === id)
  }
})

在组件中使用

<!-- Home.vue -->
<template>
  <div>
    <ul>
      <li v-for="article in articles" :key="article.id">
        <router-link :to="{ name: 'Article', params: { id: article.id } }">
          {{ article.title }}
        </router-link>
      </li>
    </ul>
  </div>
</template>

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

export default {
  setup() {
    const { articles, fetchArticles } = mapActions(['articles', 'fetchArticles'])

    onMounted(() => {
      fetchArticles()
    })

    return {
      articles
    }
  }
}
</script>
<!-- Article.vue -->
<template>
  <div>
    <h1>{{ article.title }}</h1>
    <p>{{ article.content }}</p>
  </div>
</template>

<script>
import { mapGetters } from 'vuex'

export default {
  setup() {
    const { findArticleById } = mapGetters(['findArticleById'])

    const route = useRoute()

    const article = computed(() => findArticleById(route.params.id))

    return {
      article
    }
  }
}
</script>

Vue3项目实战

小项目案例分析

我们将构建一个简单的待办事项(Todo List)应用,该应用允许用户添加、删除和标记待办事项。我们将使用Vue3的基本特性,包括组件化、路由和状态管理。

项目结构

- src
  - components
    - TodoItem.vue
    - TodoList.vue
    - AddTodo.vue
  - views
    - Home.vue
  - router
    - index.js
  - store
    - index.js
  - main.js
  - App.vue

项目实战步骤详解

  1. 项目初始化

    • 使用Vue CLI创建一个新的Vue3项目。
    • 安装Vue Router和Vuex。
  2. 组件开发

    • 创建TodoItem组件,用于显示单个待办事项。
    • 创建TodoList组件,用于显示所有待办事项。
    • 创建AddTodo组件,用于添加新的待办事项。
  3. 路由配置

    • 配置Vue Router,让应用可以导航到不同的视图。
  4. 状态管理

    • 使用Vuex管理应用的状态,包括待办事项列表。
    • 在组件中使用Vuex来添加、删除和标记待办事项。
  5. 页面开发
    • 创建Home视图,显示待办事项列表和添加新待办事项的界面。

示例代码

初始化项目
vue create todo-app
cd todo-app
npm install vue-router@next vuex@next
创建TodoItem组件
<!-- src/components/TodoItem.vue -->
<template>
  <li>
    <input type="checkbox" v-model="checked" />
    <span :class="{ completed: checked }">{{ todo.title }}</span>
    <button @click="deleteTodo">Delete</button>
  </li>
</template>

<script>
export default {
  props: {
    todo: Object
  },
  data() {
    return {
      checked: this.todo.completed
    }
  },
  methods: {
    deleteTodo() {
      this.$emit('delete', this.todo.id)
    }
  }
}
</script>

<style>
.completed {
  text-decoration: line-through;
}
</style>
创建TodoList组件
<!-- src/components/TodoList.vue -->
<template>
  <ul>
    <TodoItem v-for="todo in todos" :key="todo.id" :todo="todo" @delete="deleteTodo" />
  </ul>
</template>

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

export default {
  props: {
    todos: Array
  },
  methods: {
    deleteTodo(id) {
      this.$emit('delete', id)
    }
  }
}
</script>
创建AddTodo组件
<!-- src/components/AddTodo.vue -->
<template>
  <form @submit.prevent="addTodo">
    <input v-model="newTodo" placeholder="Add a new todo" />
    <button type="submit">Add</button>
  </form>
</template>

<script>
export default {
  data() {
    return {
      newTodo: ''
    }
  },
  methods: {
    addTodo() {
      this.$emit('add', this.newTodo)
      this.newTodo = ''
    }
  }
}
</script>
配置路由
// src/router/index.js
import { createRouter, createWebHistory } from 'vue-router'
import Home from '../views/Home.vue'

const router = createRouter({
  history: createWebHistory(),
  routes: [
    { path: '/', component: Home }
  ]
})

export default router
配置Vuex
// src/store/index.js
import { createStore } from 'vuex'

export default createStore({
  state: {
    todos: []
  },
  mutations: {
    addTodo(state, todo) {
      state.todos.push(todo)
    },
    deleteTodo(state, id) {
      state.todos = state.todos.filter(todo => todo.id !== id)
    },
    toggleTodo(state, id) {
      const todo = state.todos.find(todo => todo.id === id)
      if (todo) {
        todo.completed = !todo.completed
      }
    }
  },
  actions: {
    addTodo({ commit }, todo) {
      commit('addTodo', todo)
    },
    deleteTodo({ commit }, id) {
      commit('deleteTodo', id)
    },
    toggleTodo({ commit }, id) {
      commit('toggleTodo', id)
    }
  },
  getters: {
    todos: state => state.todos
  }
})
创建Home视图
<!-- src/views/Home.vue -->
<template>
  <div>
    <AddTodo @add="addTodo" />
    <TodoList :todos="todos" @delete="deleteTodo" />
  </div>
</template>

<script>
import { computed, onMounted } from 'vue'
import { useStore } from 'vuex'
import AddTodo from '../components/AddTodo.vue'
import TodoList from '../components/TodoList.vue'

export default {
  components: {
    AddTodo,
    TodoList
  },
  setup() {
    const store = useStore()
    const todos = computed(() => store.getters.todos)

    const addTodo = (todo) => {
      store.dispatch('addTodo', { id: Date.now(), title: todo, completed: false })
    }

    const deleteTodo = (id) => {
      store.dispatch('deleteTodo', id)
    }

    onMounted(() => {
      store.dispatch('fetchTodos')
    })

    return {
      todos,
      addTodo,
      deleteTodo
    }
  }
}
</script>
``

### 项目部署与上线

#### 打包应用

```bash
npm run build

打包后会在dist目录下生成静态文件,可以将这些文件部署到任何静态文件服务器上。

部署到服务器

  1. 安装Web服务器

    • 对于开发环境,可以使用简单的Web服务器如http-server。
    • 对于生产环境,推荐使用Nginx或Apache等成熟的Web服务器。
  2. 部署静态文件
    • dist目录中的文件复制到Web服务器的根目录。

示例代码

# 使用http-server
npm install -g http-server
cd dist
http-server
``

通过上述步骤,你可以成功构建一个简单的待办事项应用,并将其部署到服务器上。这不仅是一个完整的Vue3项目实战,也是一个良好的学习案例,可以让你更好地理解Vue3的各项特性。


这篇关于Vue3学习:新手入门与初级教程的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程