本文详细介绍了如何从零开始使用Vue3框架进行开发,包括安装步骤、创建首个Vue3项目以及基础组件的使用。文中还探讨了Vue3的数据绑定、状态管理以及路由配置,并通过实战案例展示了如何打造一个个人博客网站。
Vue3入门教程:从零开始学习Vue3框架 Vue3简介与安装什么是Vue3
Vue是一个用于构建用户界面的渐进式框架。与其它大型框架不同的是,Vue被设计为可以自底向上逐层按需集成。Vue的开发目标是通过尽可能简单的API实现响应的数据绑定和组合的视图组件。Vue3是Vue的最新版本,它对性能、API和开发体验进行了重大改进。
安装Vue3
要开始使用Vue3,首先需要安装Node.js。Node.js是一个基于Chrome V8引擎的JavaScript运行环境,它使得直接在服务器端也能运行JavaScript代码。安装Node.js后,可以通过npm(Node.js的包管理器)安装Vue CLI,它是Vue的一个命令行工具,用于快速搭建Vue项目。
- 安装Node.js(如果尚未安装):
# 下载安装包
wget https://nodejs.org/dist/v14.17.0/node-v14.17.0-linux-x64.tar.xz
# 解压
tar xf node-v14.17.0-linux-x64.tar.xz
# 进入解压后的目录
cd node-v14.17.0-linux-x64
# 将解压后的bin目录添加到环境变量
export PATH=$PATH:/path/to/unpacked/node-v14.17.0-linux-x64/bin- 安装Vue CLI:
npm install -g @vue/cli- 使用Vue CLI创建Vue项目:
vue create my-vue3-project在选择预设时,可以通过以下命令来指定使用Vue3:
vue create --defaultPreferCjs my-vue3-project此命令用于创建一个使用CJS(CommonJS)模块系统的Vue项目,CJS模块系统是Vue3默认使用的模块系统。通过这种方式,可以直接指定使用Vue3。
创建第一个Vue3项目
接下来,我们将使用Vue CLI创建一个新的Vue3项目,并在项目中添加一些基本的代码。
- 创建项目:
vue create my-vue3-project选择“Manually select features”选项,取消选择“Router”、“Vuex”、“CSS Pre-processors”和“Linter / Formatter”,然后选择“Vue 3”。
- 进入项目目录并启动开发服务器:
cd my-vue3-project
npm run serve- 在项目中添加一些基本代码。首先,打开src/App.vue文件,这是Vue项目的入口组件。
<template>
  <div id="app">
    <img alt="Vue logo" src="./assets/logo.png">
    <HelloWorld msg="Hello Vue 3 + Vite" />
  </div>
</template>
<script setup>
import HelloWorld from './components/HelloWorld.vue'
</script>
<style>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>- 在src/components/HelloWorld.vue中添加一个简单的组件:
<template>
  <div class="hello">
    <h1>{{ msg }}</h1>
  </div>
</template>
<script setup>
defineProps({
  msg: {
    type: String,
    required: true
  }
})
</script>
<style scoped>
.hello {
  text-align: center;
  margin-top: 40px;
}
</style>现在,你可以访问http://localhost:8080来查看你的第一个Vue3项目。
组件的基本结构
组件是Vue应用的基本构建块。每个组件都有自己的视图模板、逻辑和数据模型。在Vue中,组件的定义通常包含三个主要部分:模板(template)、脚本(script)和样式(style)。以下是一个简单的组件结构:
<template>
  <div>
    <h1>{{ title }}</h1>
    <p>{{ message }}</p>
  </div>
</template>
<script>
import { ref } from 'vue';
export default {
  name: 'MyComponent',
  setup() {
    const title = ref('Hello, Vue3');
    const message = ref('This is a simple component');
    return {
      title,
      message
    };
  }
};
</script>
<style scoped>
h1 {
  color: #343a40;
  font-size: 1.5em;
}
p {
  color: #6c757d;
  font-size: 1em;
}
</style>Props和Events的使用
Props(属性)允许你将数据从父组件传入子组件。Events(事件)允许子组件向父组件传递消息。以下是一个使用Props和Events的简单示例:
- 在父组件中定义Props和Events:
<template>
  <div>
    <child-component :message="parentMessage" @child-event="handleChildEvent" />
  </div>
</template>
<script>
import { ref } from 'vue';
import ChildComponent from './ChildComponent.vue';
export default {
  components: {
    ChildComponent
  },
  setup() {
    const parentMessage = ref('Hello from Parent');
    const handleChildEvent = (msg) => {
      console.log('Message from child:', msg);
    };
    return {
      parentMessage,
      handleChildEvent
    };
  }
};
</script>- 在子组件中使用Props和触发Events:
<template>
  <div>
    <p>{{ message }}</p>
    <button @click="sendMessage">Send Message to Parent</button>
  </div>
</template>
<script>
import { ref, defineProps, defineEmits } from 'vue';
export default {
  props: {
    message: {
      type: String,
      required: true
    }
  },
  emits: ['child-event'],
  setup(props, { emit }) {
    const sendMessage = () => {
      emit('child-event', 'Hello from Child');
    };
    return { sendMessage };
  }
};
</script>插槽(Slots)的应用
插槽允许你将父组件的内容注入到子组件的特定位置。以下是一个使用默认插槽和具名插槽的简单示例:
- 定义一个带有插槽的子组件:
<template>
  <div>
    <header>
      <slot name="header">Default Header</slot>
    </header>
    <main>
      <slot>Default Content</slot>
    </main>
    <footer>
      <slot name="footer">Default Footer</slot>
    </footer>
  </div>
</template>
<script>
export default {
  name: 'SlotComponent'
};
</script>- 在父组件中使用插槽:
<template>
  <div>
    <slot-component>
      <template v-slot:header>
        <h1>Custom Header</h1>
      </template>
      <p>This is custom content</p>
      <template v-slot:footer>
        <p>Custom Footer</p>
      </template>
    </slot-component>
  </div>
</template>
<script>
import SlotComponent from './SlotComponent.vue';
export default {
  components: {
    SlotComponent
  }
};
</script>组件组合示例
为了展示如何将组件组合成更复杂的视图,假设我们有一个博客应用,它包含一个主页和文章详情页。主页展示文章列表,点击文章标题可以跳转到文章详情页。
- 主页组件(Home.vue):
<template>
  <div>
    <h1>Blog Posts</h1>
    <ul>
      <li v-for="post in posts" :key="post.id">
        <router-link :to="`/post/${post.id}`">{{ post.title }}</router-link>
        <p>{{ post.summary }}</p>
      </li>
    </ul>
  </div>
</template>
<script setup>
import { ref, onMounted } from 'vue';
import { useRouter } from 'vue-router';
const router = useRouter();
const posts = ref([]);
onMounted(() => {
  fetchPosts();
});
const fetchPosts = async () => {
  const response = await fetch('/api/posts');
  const data = await response.json();
  posts.value = data;
};
</script>
<style scoped>
ul {
  list-style-type: none;
  padding: 0;
}
li {
  margin: 10px 0;
}
</style>- 文章详情组件(PostDetail.vue):
<template>
  <div>
    <h1>{{ post.title }}</h1>
    <p>{{ post.content }}</p>
  </div>
</template>
<script setup>
import { ref, onMounted } from 'vue';
import { useRoute } from 'vue-router';
const post = ref({});
const route = useRoute();
onMounted(() => {
  fetchPost();
});
const fetchPost = async () => {
  const { id } = route.params;
  const response = await fetch(`/api/posts/${id}`);
  const data = await response.json();
  post.value = data;
};
</script>
<style scoped>
h1 {
  color: #343a40;
  font-size: 1.5em;
}
p {
  color: #6c757d;
  font-size: 1em;
}
</style>- 路由定义(router/index.js):
import { createRouter, createWebHistory } from 'vue-router';
import Home from './views/Home.vue';
import PostDetail from './views/PostDetail.vue';
const routes = [
  { path: '/', component: Home },
  { path: '/post/:id', component: PostDetail }
];
const router = createRouter({
  history: createWebHistory(),
  routes
});
export default router;模板语法
模板语法是Vue的视图层描述语言。通过模板语法,你可以方便地将DOM绑定到Vue实例的数据层上。以下是一些常见的模板语法示例:
- 插值(Interpolation):
<p>{{ message }}</p>- 指令(Directives):
<div v-if="flag"></div>
<div v-for="item in items" :key="item.id">{{ item.name }}</div>- 事件绑定(Event Handling):
<button @click="increment">Click me</button>v-bind与v-model的使用
v-bind用于绑定元素属性,而v-model用于双向数据绑定。以下是一些具体的示例:
- 使用v-bind绑定属性:
<template>
  <div>
    <img v-bind:src="imageSrc" alt="Image" />
  </div>
</template>
<script>
import { ref } from 'vue';
export default {
  setup() {
    const imageSrc = ref('https://example.com/image.jpg');
    return { imageSrc };
  }
};
</script>- 使用v-model进行双向绑定:
<template>
  <div>
    <input v-model="message" type="text" placeholder="Type something..." />
    <p>{{ message }}</p>
  </div>
</template>
<script>
import { ref } from 'vue';
export default {
  setup() {
    const message = ref('');
    return { message };
  }
};
</script>
<script setup>
import { ref } from 'vue';
const message = ref('');
// 当输入框中的值变化时,绑定的变量会自动更新
message.value = 'Hello, Vue 3';
</script>自定义指令
自定义指令允许你在DOM元素上添加自定义行为。以下是一个简单的自定义指令示例:
- 定义自定义指令:
import { createApp } from 'vue';
const app = createApp(App);
app.directive('focus', {
  mounted(el) {
    el.focus();
  }
});- 在模板中使用自定义指令:
<template>
  <div>
    <input v-focus type="text" placeholder="Get focus" />
  </div>
</template>使用Composition API管理状态
Composition API是Vue3中新增的API,它提供了更灵活的状态管理方式。以下是一个使用Composition API管理状态的简单示例:
<template>
  <div>
    <p>{{ count }}</p>
    <button @click="increment">Increment</button>
  </div>
</template>
<script setup>
import { ref, onMounted } from 'vue';
const count = ref(0);
const increment = () => {
  count.value++;
};
onMounted(() => {
  console.log('Component is mounted');
});
</script>响应式原理简介
Vue的响应式系统基于其内部的依赖追踪系统。当数据发生变化时,Vue会自动更新受影响的视图部分。以下是一个使用响应式API的简单示例:
import { reactive, watch } from 'vue';
const state = reactive({
  count: 0
});
watch(() => state.count, (newValue, oldValue) => {
  console.log(`Count changed from ${oldValue} to ${newValue}`);
});
setInterval(() => {
  state.count++;
}, 1000);使用Vuex进行全局状态管理
Vuex是一个集中式状态管理库,适用于Vue应用程序。它可以帮助你更好地管理和共享状态。以下是一个使用Vuex的基本示例:
- 安装Vuex:
npm install vuex@next --save- 创建Vuex store:
import { createStore } from 'vuex';
export default createStore({
  state: {
    counter: 0
  },
  mutations: {
    increment(state) {
      state.counter++;
    }
  },
  actions: {
    increment({ commit }) {
      commit('increment');
    }
  }
});- 在Vue项目中使用Vuex:
<template>
  <div>
    <p>{{ counter }}</p>
    <button @click="incrementCounter">Increment</button>
  </div>
</template>
<script>
import { mapState, mapActions } from 'vuex';
export default {
  computed: {
    ...mapState(['counter'])
  },
  methods: {
    ...mapActions(['increment'])
  }
};
</script>
<script setup>
import { useStore } from 'vue';
const store = useStore();
console.log(store.state.counter); // 输出初始的counter值
</script>Vue Router的基本使用
Vue Router是Vue官方的路由库,用于实现单页面应用的路由功能。以下是一个使用Vue Router的基本示例:
- 安装Vue Router:
npm install vue-router@next --save- 创建路由配置:
import { createRouter, createWebHistory } from 'vue-router';
import Home from './views/Home.vue';
import About from './views/About.vue';
const routes = [
  { path: '/', component: Home },
  { path: '/about', component: About }
];
const router = createRouter({
  history: createWebHistory(),
  routes
});
export default router;- 在主应用中使用路由:
<template>
  <div>
    <router-view></router-view>
  </div>
</template>
<script>
import router from './router';
export default {
  router
};
</script>路由导航与参数传递
你可以在路由之间传递参数,这可以通过路由的动态参数来实现。以下是一个传递参数的示例:
- 定义带有动态参数的路由:
const routes = [
  { path: '/user/:id', component: User }
];- 在组件中获取传递的参数:
<template>
  <div>
    <p>User ID: {{ userId }}</p>
  </div>
</template>
<script>
import { useRoute } from 'vue-router';
export default {
  setup() {
    const route = useRoute();
    const userId = route.params.id;
    return { userId };
  }
};
</script>项目文件结构规划
一个合理的项目结构可以帮助你更好地组织代码,以下是一个简单的项目结构示例:
my-vue3-project/
├── public/
│   └── index.html
├── src/
│   ├── assets/
│   ├── components/
│   ├── views/
│   ├── App.vue
│   ├── main.js
│   └── router/
│       └── index.js
├── package.json
└── README.md项目需求分析
- 主页:展示博客文章列表,包括标题、作者、发布日期和简短摘要。
- 文章详情页:展示文章的详细内容,包括评论区。
- 文章创建与编辑:管理员可以创建和编辑文章。
- 用户注册和登录:用户可以注册和登录,注册后可以发布评论。
- 后台管理:管理员可以管理所有文章和用户。
功能模块划分
- 
主页模块: - Home.vue:展示博客文章列表。
- ArticleCard.vue:展示文章卡片。
- ArticleList.vue:展示所有文章列表。
- ArticleForm.vue:创建和编辑文章表单。
 
- 
文章详情模块: - ArticleDetail.vue:展示文章详细内容。
- ArticleComment.vue:展示和提交评论。
 
- 
文章管理模块: - ArticleStore.js:文章数据存储和管理。
 
- 
用户管理模块: - UserRegister.vue:用户注册表单。
- UserLogin.vue:用户登录表单。
- UserStore.js:用户数据存储和管理。
 
- 后台管理模块:
- AdminDashboard.vue:后台管理首页。
- AdminArticleList.vue:展示所有文章列表。
- AdminUserList.vue:展示所有用户列表。
 
具体实现代码示例
主页模块
- Home.vue:
<template>
  <div>
    <h1>Blog Posts</h1>
    <ul>
      <li v-for="post in posts" :key="post.id">
        <router-link :to="`/post/${post.id}`">{{ post.title }}</router-link>
        <p>{{ post.summary }}</p>
      </li>
    </ul>
  </div>
</template>
<script setup>
import { ref, onMounted } from 'vue';
import { useRouter } from 'vue-router';
import { fetchPosts } from '../../services/articleService';
const router = useRouter();
const posts = ref([]);
onMounted(() => {
  fetchPosts().then(data => {
    posts.value = data;
  });
});
</script>
<style scoped>
ul {
  list-style-type: none;
  padding: 0;
}
li {
  margin: 10px 0;
}
</style>- ArticleCard.vue:
<template>
  <div class="card">
    <h2>{{ post.title }}</h2>
    <p>{{ post.summary }}</p>
  </div>
</template>
<script setup>
import { defineProps } from 'vue';
defineProps({
  post: {
    type: Object,
    required: true
  }
});
</script>
<style scoped>
.card {
  border: 1px solid #ccc;
  padding: 10px;
  margin: 10px 0;
  border-radius: 5px;
}
</style>文章详情模块
- ArticleDetail.vue:
<template>
  <div>
    <h1>{{ post.title }}</h1>
    <p>{{ post.content }}</p>
    <ArticleComment :postId="post.id" />
  </div>
</template>
<script setup>
import { ref, onMounted } from 'vue';
import { useRoute } from 'vue-router';
import { fetchPost } from '../../services/articleService';
import ArticleComment from '../../components/ArticleComment.vue';
const route = useRoute();
const post = ref({});
onMounted(() => {
  fetchPost(route.params.id).then(data => {
    post.value = data;
  });
});
</script>
<style scoped>
h1 {
  color: #343a40;
  font-size: 1.5em;
}
p {
  color: #6c757d;
  font-size: 1em;
}
</style>- ArticleComment.vue:
<template>
  <div>
    <h2>Comments</h2>
    <ul>
      <li v-for="comment in comments" :key="comment.id">
        <p>{{ comment.content }}</p>
      </li>
    </ul>
    <form @submit.prevent="submitComment">
      <textarea v-model="commentContent" placeholder="Type your comment..." />
      <button type="submit">Submit</button>
    </form>
  </div>
</template>
<script setup>
import { ref, onMounted } from 'vue';
import { fetchComments, addComment } from '../../services/commentService';
const postId = ref(null);
const commentContent = ref('');
const comments = ref([]);
const submitComment = () => {
  addComment(postId.value, commentContent.value).then(() => {
    commentContent.value = '';
    fetchComments(postId.value);
  });
};
onMounted(() => {
  if (postId.value) {
    fetchComments(postId.value).then(data => {
      comments.value = data;
    });
  }
});
</script>
<style scoped>
textarea {
  width: 100%;
  margin-bottom: 10px;
}
button {
  background-color: #28a745;
  color: white;
  border: none;
  padding: 5px 10px;
  cursor: pointer;
}
</style>文章管理模块
- ArticleList.vue:
<template>
  <div>
    <h1>Article List</h1>
    <ul>
      <li v-for="post in posts" :key="post.id">
        <router-link :to="`/post/${post.id}`">{{ post.title }}</router-link>
        <button @click="deletePost(post.id)">Delete</button>
      </li>
    </ul>
  </div>
</template>
<script setup>
import { ref, onMounted } from 'vue';
import { fetchPosts } from '../../services/articleService';
const posts = ref([]);
onMounted(() => {
  fetchPosts().then(data => {
    posts.value = data;
  });
});
const deletePost = (postId) => {
  // 实现删除逻辑
};
</script>
<style scoped>
ul {
  list-style-type: none;
  padding: 0;
}
li {
  margin: 10px 0;
}
</style>- ArticleForm.vue:
<template>
  <div>
    <h2>Article Form</h2>
    <form @submit.prevent="submitArticle">
      <label>
        Title:
        <input v-model="title" type="text" />
      </label>
      <label>
        Content:
        <textarea v-model="content" placeholder="Type your article..." />
      </label>
      <button type="submit">Submit</button>
    </form>
  </div>
</template>
<script setup>
import { ref } from 'vue';
const title = ref('');
const content = ref('');
const submitArticle = () => {
  // 实现提交逻辑
};
</script>
<style scoped>
input, textarea {
  width: 100%;
  margin-bottom: 10px;
}
button {
  background-color: #28a745;
  color: white;
  border: none;
  padding: 5px 10px;
  cursor: pointer;
}
</style>项目部署与上线
部署Vue项目可以通过几种方法实现,以下是两种常见的方法:
- 使用Vite部署:
npm run build构建完成后,将生成的dist文件夹上传到服务器。
- 使用GitHub Pages部署:
npm run build
npm run deploy构建完成后,将生成的dist文件夹中的内容上传到GitHub Pages。
部署完成后,可以通过浏览器访问你的博客网站。
总结
通过以上步骤,你已经掌握了Vue3的基本概念和开发流程,从安装到项目结构规划,再到实战演练,你已经完成了一个简单的博客网站的开发。如果你想要深入学习Vue3,建议参考Vue官方文档或参加在线课程,例如Muicoo提供的Vue3教程。
 
		 随时随地看视频
随时随地看视频 
				 
				 
				 
				 
				