Javascript

Vue学习:从入门到简单项目实战

本文主要是介绍Vue学习:从入门到简单项目实战,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
概述

本文全面介绍了Vue.js的基础知识和核心特性,包括响应式数据绑定、组件化开发和虚拟DOM等概念。文章还详细讲解了Vue的学习路径,涵盖了安装配置、项目搭建以及组件化开发等多个方面,帮助读者快速掌握Vue.js的学习。

Vue基础知识介绍
Vue框架简介

Vue.js是由尤雨青(Evan You)开发的一个前端JavaScript框架。它具有轻量、易用、灵活和可扩展性等特点,适用于从小型到大型的单页应用开发。Vue的核心理念是为前端开发人员提供一个简洁、高效、渐进式的工具,以帮助开发人员构建动态的用户界面。

Vue的核心特性包括:

  • 响应式数据绑定:Vue使用了一种称为“依赖追踪”的技术,能够追踪数据的变化,并自动更新视图。
  • 组件化开发:Vue推崇组件化思想,将复杂的应用拆分为多个小的、可复用的组件,每个组件负责一部分功能。
  • 虚拟DOM:Vue使用虚拟DOM技术,以提高渲染性能。虚拟DOM允许Vue应用在DOM更新时更高效地操作DOM。
  • 双向数据绑定:Vue通过v-model指令实现视图与数据之间的双向绑定,使得数据变化能够直接反映到视图上,反之亦然。
  • 模板语法:Vue提供了一种基于HTML的模板语法,用于在HTML模板中书写指令和逻辑,从而更直观地描述组件的视图。
Vue的核心概念
  1. 组件 (Component):组件是 Vue 中的重要概念,它代表了一个可重用的模块,可以封装 HTML 代码、样式、逻辑等。每个组件都有自己的模板、数据、方法等,可以在应用中进行复用。
  2. 数据绑定 (Data Binding):Vue通过数据绑定,实现了数据变化自动更新视图的功能。Vue提供了v-bind指令,用于实现单向数据绑定,而v-model指令则用于实现双向数据绑定。
  3. 模板 (Template):Vue中的模板可以看作是HTML结构的一部分,它定义了视图的结构,包含HTML标签、Vue指令、变量等。
  4. 指令 (Directives):Vue提供了多个内置指令,如v-ifv-forv-bind等,这些指令可以操作DOM或更新视图。
  5. 生命周期 (Lifecycle):Vue组件实例从创建到销毁的整个过程称为生命周期。它包括了几个重要的生命周期钩子,如createdmounted等,允许在组件的各个阶段执行特定的操作。
  6. 路由 (Routing):Vue Router 是 Vue.js 的官方路由库,用于实现单页面应用的路由管理。它允许用户在不同的视图之间导航,同时保持页面的动态更新。
  7. 状态管理 (State Management):Vue中推荐使用vuex进行状态管理。vuex是一个专为 Vue.js 应用程序开发的状态管理模式和可组合的可预测的状态容器。
  8. 插件 (Plugins):Vue允许通过插件来扩展其功能,如vue-routervuex等。
Vue响应式原理与数据绑定
响应式系统概述

Vue通过依赖追踪机制实现了响应式系统。当数据发生变化时,Vue会自动更新视图。主要步骤如下:

  • 初始化阶段:Vue通过Object.defineProperty(在 Vue 2.x 中)或Proxy(在 Vue 3.x 中)对数据对象进行拦截。
  • 依赖收集:当访问数据属性时,Vue会将该依赖添加到相应的观察者 (Watcher) 列表中。
  • 数据变更:当数据变更时,Vue会触发相应的 Watcher,从而更新视图。
// 示例代码:响应式初始化
const data = {
  count: 0
};

// 使用Object.defineProperty实现响应式
const observe = (obj) => {
  if (typeof obj !== 'object') return;

  Object.keys(obj).forEach((key) => {
    defineReactive(obj, key, obj[key]);
  });
};

const defineReactive = (obj, key, value) => {
  Object.defineProperty(obj, key, {
    get() {
      return value;
    },
    set(newVal) {
      if (newVal === value) return;
      value = newVal;
      console.log(`属性 ${key} 的值已更新为 ${newVal}`);
    }
  });
};

observe(data);
data.count = 1; // 输出:属性 count 的值已更新为 1
数据绑定的实现

基本数据绑定

<template>
  <div>
    <p>{{ message }}</p>
    <input v-model="message">
  </div>
</template>

<script>
export default {
  data() {
    return {
      message: 'Hello, World!'
    }
  }
}
</script>

v-model双向绑定数据

<template>
  <div>
    <p>{{ message }}</p>
    <input v-model="message">
  </div>
</template>

<script>
export default {
  data() {
    return {
      message: 'Hello, World!'
    }
  }
}
</script>

复杂对象的双向绑定

<template>
  <div>
    <p>{{ user.name }}</p>
    <input v-model="user.name">
  </div>
</template>

<script>
export default {
  data() {
    return {
      user: {
        name: 'John'
      }
    }
  }
}
</script>
Vue项目搭建
创建第一个Vue项目

使用原生Vue创建项目

  1. 创建项目文件夹,例如 my-vue-project
  2. 初始化一个新的 npm 项目:
npm init -y
  1. 安装 Vue.js:
npm install vue@2.6.14 --save
  1. 创建 Vue 实例文件 src/index.js
import Vue from 'vue';
import App from './App.vue';

new Vue({
  el: '#app',
  components: { App },
  template: '<App/>'
});
  1. 创建基础模板 public/index.html
<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
<title>Vue项目</title>
</head>
<body>
<div id="app"></div>
<!-- 引入Vue.js -->
<script class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="/js/vue.js"></script>
<!-- 引入本项目js -->
<script class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="/js/index.js"></script>
</body>
</html>
  1. 创建 Vue 组件文件 src/App.vue
<template>
  <div>
    <h1>{{ message }}</h1>
  </div>
</template>

<script>
export default {
  data() {
    return {
      message: 'Hello, Vue!'
    }
  }
}
</script>

使用Vue CLI快速搭建项目

Vue CLI 是 Vue 的脚手架工具,用于快速搭建项目。可以通过以下步骤创建一个 Vue 项目:

  1. 安装 Vue CLI:
npm install -g @vue/cli
  1. 创建新项目:
vue create my-vue-project
  1. 按照提示选择所需的配置,例如模板、插件等。

  2. 进入项目目录并启动开发服务器:
cd my-vue-project
npm run serve

这将启动开发服务器并开启热重载功能,便于实时查看修改后的效果。

项目目录结构解析

一个典型的 Vue 项目目录结构如下:

my-vue-project/
  ├── node_modules/
  ├── public/
  │   └── index.html
  ├── src/
  │   ├── assets/
  │   ├── components/
  │   │   └── HelloWorld.vue
  │   ├── App.vue
  │   ├── main.js
  │   └── router/
  │       └── index.js
  ├── .gitignore
  ├── babel.config.js
  ├── package.json
  └── vue.config.js
  • public/:存放静态资源,如 index.html
  • src/:存放源代码,包括组件、样式、路由配置等。
  • assets/:存放静态资源文件,如图片、字体等。
  • components/:存放 Vue 组件。
  • App.vue:应用的根组件。
  • main.js:应用的入口文件。
  • router/:存放路由配置。
  • .gitignore:配置 Git 忽略的文件。
  • babel.config.js:配置 Babel。
  • package.json:存放项目配置和依赖。
  • vue.config.js:配置 Vue CLI 选项。
Vue组件化开发
组件的基本使用

创建组件

创建一个名为 HelloWorld.vue 的组件:

<template>
  <div>
    <h1>{{ message }}</h1>
  </div>
</template>

<script>
export default {
  name: 'HelloWorld',
  data() {
    return {
      message: 'Hello, World!'
    }
  }
}
</script>

<style scoped>
h1 {
  color: #42b983;
}
</style>

在 App.vue 中使用组件

<template>
  <div id="app">
    <HelloWorld />
  </div>
</template>

<script>
import HelloWorld from './components/HelloWorld.vue';

export default {
  name: 'App',
  components: {
    HelloWorld
  }
}
</script>

在模板中使用组件

<template>
  <div id="app">
    <h1>App Component</h1>
    <hello-world></hello-world>
  </div>
</template>

组件的通信

父组件向子组件传递数据

父组件通过 props 向子组件传递数据。

<!-- ParentComponent.vue -->
<template>
  <div>
    <ChildComponent :message="parentMessage" />
  </div>
</template>

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

export default {
  name: 'ParentComponent',
  data() {
    return {
      parentMessage: 'Hello from Parent'
    }
  },
  components: {
    ChildComponent
  }
}
</script>
<!-- ChildComponent.vue -->
<template>
  <div>
    <p>{{ message }}</p>
  </div>
</template>

<script>
export default {
  name: 'ChildComponent',
  props: ['message']
}
</script>

子组件向父组件传递数据

子组件通过 $emit 触发自定义事件,将数据传递给父组件。

<!-- ParentComponent.vue -->
<template>
  <div>
    <ChildComponent @child-event="handleChildEvent" />
  </div>
</template>

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

export default {
  name: 'ParentComponent',
  methods: {
    handleChildEvent(data) {
      console.log('Child event received:', data);
    }
  },
  components: {
    ChildComponent
  }
}
</script>
<!-- ChildComponent.vue -->
<template>
  <div>
    <button @click="sendDataToParent">Send Data</button>
  </div>
</template>

<script>
export default {
  name: 'ChildComponent',
  methods: {
    sendDataToParent() {
      this.$emit('child-event', 'Hello from Child');
    }
  }
}
</script>
深入理解Props与Events

Props

props 是父组件向子组件传递数据的一种方式。子组件通过 props 接收数据,可以在模板中使用这些数据。

<!-- ChildComponent.vue -->
<template>
  <div>
    <p>{{ message }}</p>
  </div>
</template>

<script>
export default {
  name: 'ChildComponent',
  props: {
    message: {
      type: String,
      required: true
    }
  }
}
</script>

Events

子组件通过 $emit 触发自定义事件,将数据传递给父组件。父组件通过监听这些事件来接收数据。

<!-- ChildComponent.vue -->
<template>
  <div>
    <button @click="sendDataToParent">Send Data</button>
  </div>
</template>

<script>
export default {
  name: 'ChildComponent',
  methods: {
    sendDataToParent() {
      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 {
  name: 'ParentComponent',
  methods: {
    handleChildEvent(data) {
      console.log('Child event received:', data);
    }
  },
  components: {
    ChildComponent
  }
}
</script>
Vue路由与组件间导航
Vue Router安装与配置

首先,安装 Vue Router:

npm install vue-router@3.1.6 --save

然后,在项目中引入 Vue Router 并进行配置。

基本配置

// router/index.js
import Vue from 'vue';
import Router from 'vue-router';
import Home from '../components/Home.vue';
import About from '../components/About.vue';

Vue.use(Router);

export default new Router({
  routes: [
    {
      path: '/',
      name: 'Home',
      component: Home
    },
    {
      path: '/about',
      name: 'About',
      component: About
    }
  ]
});

在 main.js 中使用路由

// src/main.js
import Vue from 'vue';
import App from './App.vue';
import router from './router';

new Vue({
  el: '#app',
  router,
  render: h => h(App)
});
路由的基本使用

链接组件

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

<script>
export default {
  name: 'App'
}
</script>

路由守卫

// router/index.js
import Vue from 'vue';
import Router from 'vue-router';
import Home from '../components/Home.vue';
import About from '../components/About.vue';
import Auth from '../components/Auth.vue';

Vue.use(Router);

const router = new Router({
  routes: [
    {
      path: '/',
      name: 'Home',
      component: Home
    },
    {
      path: '/about',
      name: 'About',
      component: About
    },
    {
      path: '/auth',
      name: 'Auth',
      component: Auth
    }
  ]
});

router.beforeEach((to, from, next) => {
  if (to.name === 'Auth' && !isAuthenticated()) {
    next('/about');
  } else {
    next();
  }
});

export default router;

function isAuthenticated() {
  return true; // 模拟认证逻辑
}
路由的高级用法

嵌套路由

<template>
  <div>
    <router-link to="/">Home</router-link>
    <router-link to="/about">About</router-link>
    <router-link to="/about/child1">Child1</router-link>
    <router-link to="/about/child2">Child2</router-link>
    <router-view></router-view>
  </div>
</template>

<script>
export default {
  name: 'App'
}
</script>
// router/index.js
import Vue from 'vue';
import Router from 'vue-router';
import Home from '../components/Home.vue';
import About from '../components/About.vue';
import Child1 from '../components/Child1.vue';
import Child2 from '../components/Child2.vue';

Vue.use(Router);

const router = new Router({
  routes: [
    {
      path: '/',
      name: 'Home',
      component: Home
    },
    {
      path: '/about',
      name: 'About',
      component: About,
      children: [
        {
          path: 'child1',
          name: 'Child1',
          component: Child1
        },
        {
          path: 'child2',
          name: 'Child2',
          component: Child2
        }
      ]
    }
  ]
});

export default router;

动态路由

<template>
  <div>
    <router-link to="/user/123">User 123</router-link>
    <router-link to="/user/456">User 456</router-link>
    <router-view></router-view>
  </div>
</template>

<script>
export default {
  name: 'App'
}
</script>
// router/index.js
import Vue from 'vue';
import Router from 'vue-router';
import User from '../components/User.vue';

Vue.use(Router);

const router = new Router({
  routes: [
    {
      path: '/user/:id',
      name: 'User',
      component: User,
      props: true
    }
  ]
});

export default router;

动态路由组件

<template>
  <div>
    <router-link to="/user/123">User 123</router-link>
    <router-link to="/user/456">User 456</router-link>
    <router-view></router-view>
  </div>
</template>

<script>
export default {
  name: 'App'
}
</script>
// router/index.js
import Vue from 'vue';
import Router from 'vue-router';
import User from '../components/User.vue';

Vue.use(Router);

const router = new Router({
  routes: [
    {
      path: '/user/:id',
      name: 'User',
      component: User,
      props: route => ({ id: route.params.id })
    }
  ]
});

export default router;
Vue项目实战
构建简单的待办事项应用

项目结构

my-todo-app/
  ├── node_modules/
  ├── public/
  │   └── index.html
  ├── src/
  │   ├── assets/
  │   ├── components/
  │   │   └── TodoList.vue
  │   │   └── TodoInput.vue
  │   ├── App.vue
  │   ├── main.js
  │   └── router/
  │       └── index.js
  ├── .gitignore
  ├── babel.config.js
  ├── package.json
  └── vue.config.js

TodoInput.vue 组件

<template>
  <div>
    <input v-model="newTodo" @keyup.enter="addTodo">
    <button @click="addTodo">Add Todo</button>
  </div>
</template>

<script>
export default {
  data() {
    return {
      newTodo: ''
    }
  },
  methods: {
    addTodo() {
      if (this.newTodo.trim()) {
        this.$emit('add-todo', this.newTodo);
        this.newTodo = '';
      }
    }
  }
}
</script>

TodoList.vue 组件

<template>
  <div>
    <ul>
      <li v-for="(todo, index) in todos" :key="index" @click="completeTodo(index)">
        {{ todo.text }} <button @click="removeTodo(index)">Remove</button>
      </li>
    </ul>
  </div>
</template>

<script>
export default {
  props: ['todos'],
  methods: {
    removeTodo(index) {
      this.$emit('remove-todo', index);
    },
    completeTodo(index) {
      this.$emit('complete-todo', index);
    }
  }
}
</script>

App.vue 文件

<template>
  <div>
    <h1>Todo List</h1>
    <TodoInput @add-todo="addTodo" />
    <TodoList :todos="todos" @remove-todo="removeTodo" @complete-todo="completeTodo" />
  </div>
</template>

<script>
import TodoInput from './components/TodoInput.vue';
import TodoList from './components/TodoList.vue';

export default {
  components: {
    TodoInput,
    TodoList
  },
  data() {
    return {
      todos: []
    }
  },
  methods: {
    addTodo(todo) {
      this.todos.push({ text: todo, completed: false });
    },
    removeTodo(index) {
      this.todos.splice(index, 1);
    },
    completeTodo(index) {
      this.todos[index].completed = true;
    }
  }
}
</script>
使用Vue构建个人博客首页

项目结构

my-blog-app/
  ├── node_modules/
  ├── public/
  │   └── index.html
  ├── src/
  │   ├── assets/
  │   ├── components/
  │   │   └── BlogPost.vue
  │   ├── App.vue
  │   ├── main.js
  │   └── router/
  │       └── index.js
  ├── .gitignore
  ├── babel.config.js
  ├── package.json
  └── vue.config.js

BlogPost.vue 组件

<template>
  <div>
    <h2>{{ post.title }}</h2>
    <p>{{ post.content }}</p>
  </div>
</template>

<script>
export default {
  props: ['post']
}
</script>

App.vue 文件

<template>
  <div>
    <h1>My Blog</h1>
    <BlogPost v-for="post in posts" :key="post.id" :post="post" />
  </div>
</template>

<script>
import BlogPost from './components/BlogPost.vue';

export default {
  components: {
    BlogPost
  },
  data() {
    return {
      posts: [
        { id: 1, title: 'First Post', content: 'This is the first post in my blog.' },
        { id: 2, title: 'Second Post', content: 'This is the second post in my blog.' }
      ]
    }
  }
}
</script>
项目部署与上线

部署到GitHub Pages

  1. 使用 npm run build 构建应用。
  2. 将生成的 dist 文件夹上传到 GitHub 仓库。
  3. 设置 GitHub Pages,将仓库指向 gh-pages 分支。
# 构建应用
npm run build

# 将dist文件夹上传到GitHub仓库
git add dist
git commit -m "Build dist"
git push origin master

# 设置GitHub Pages
# 在GitHub仓库设置中,选择"Settings" -> "GitHub Pages",将源设置为"gh-pages"分支
  1. package.json 中添加部署设置:
{
  "name": "my-project",
  "version": "1.0.0",
  "homepage": "https://username.github.io/my-project"
}

部署到Netlify

  1. 注册 Netlify 账号。
  2. 连接 GitHub 仓库。
  3. 选择构建设置,指定 npm run build 作为构建命令。
  4. 发布应用。
# 构建应用
npm run build

# 连接GitHub仓库到Netlify
# 在Netlify网站中,选择"New site from Git",连接GitHub仓库

# 设置构建设置
# 在Netlify网站中,选择"Build & Deploy" -> "Build settings",指定"Build Command"为"npm run build","Publish directory"为"dist"

部署到Vercel

  1. 注册 Vercel 账号。
  2. 连接 GitHub 仓库。
  3. 选择构建设置,指定 npm run build 作为构建命令。
  4. 发布应用。
# 构建应用
npm run build

# 连接GitHub仓库到Vercel
# 在Vercel网站中,选择"New Project",连接GitHub仓库

# 设置构建设置
# 在Vercel网站中,选择"Build & Output" -> "Build settings",指定"Build Command"为"npm run build","Output Directory"为"dist"

通过以上步骤,可以将 Vue 应用部署到不同的平台上,实现线上发布。

这篇关于Vue学习:从入门到简单项目实战的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!