博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Vue 3.0 (CompostionAPI + VueRouter + Axios + Bootstrap + Sass) 文章管理项目
阅读量:3948 次
发布时间:2019-05-24

本文共 13906 字,大约阅读时间需要 46 分钟。

Vue 3.0 CompostionAPI + VueRouter + Axios + Bootstrap + Sass 文章管理项目

1. Vue 3.0 介绍和脚手架文档

  • Vue 3.0 的使用需要 VueCli 4.5
    • 更新脚手架
      • yarn global add @vue/cli
      • npm install -g @vue/cli

2. Vue 3.0 快速入门指南

2.1 Vue 3.0 搭建脚手架项目

  • 创建项目
    • vue create 项目名
    • 根据个人情况设置配置

2.2 Vue 3.0 文件结构梳理

在这里插入图片描述

  • node_modules: 这个目录存放的是项目的所有依赖,即 npm install 命令下载下来的文件
  • public: 静态资源
  • index.html: 主页
  • src: 这个目录下存放项目的源码,即开发者写的代码放在这里
  • assets: 静态文件
  • components: 目录用来存放组件(一些可复用,非独立的页面)
  • App.vue: 是一个Vue根组件,也是项目的第一个Vue组件
  • main.js: 整个项目的入口文件
  • package.json: 定义了项目的所有依赖,包括开发时依赖和发布时依赖
  • .babel.config.js: 该文件是babel的配置文件

2.3 Vue 3.0 组件的组成

  • 组件组成
    • html 结构部分
    • script 逻辑部分
    • style 样式部分

2.4 Vue 3.0 CompositionAPI

3. Vue 3.0 组件

3.1 Vue 3.0 组件拆分

  • CounterView.vue
  • App.vue

3.2 Vue 3.0 属性传值

  • CounterView.vue
  • App.vue

3.3 Vue 3.0 事件注册

  • CounterController.vue
  • App.vue

3.4 Vue 3.0 调整项目引入 Bootstrap

  • 引入 Bootstrap
    • npm install bootstrap@4.5.2 --save
  • App.vue

3.5 Vue 3.0 模拟数据和属性传值

  • 模拟列表内容数据,并将数据传入列表组件
  • ResourceHome.vue
...setup(){
const data = reactive({
resources: [ {
_id: "1", title: "2021 前端面试 | “HTML + CSS + JS”专题", description: "BAT面试1000题——数据结构(841~850题)", type: "video", link: "" }, {
_id: "2", title: "一篇搞定前端高频手撕算法题(36道)", description: "《JavaScript 20 年》中文在线版发布", type: "book", link: "" }, {
_id: "3", title: "32个手撕JS,彻底摆脱初级前端(面试高频)", description: "56 道高频 JavaScript 与 ES6+ 的面试题及答案", type: "video", link: "" }, {
_id: "4", title: "字节跳动2020届秋招提前批前端面经", description: "初入WEB前端的新手,掌握这些核心知识点,年薪冲破20W", type: "book", link: "" }, {
_id: "5", title: "前方预警!史上最全前端面试题来袭!(附答案)", description: "做一个数据可视化项目的难点在什么地方?", type: "video", link: "" }, {
_id: "6", title: "JavaScript数据类型详解", description: "nodejs的websocket的服务器端是如何实现的?", type: "book", link: "" }, ] }) return {
// 解包 ...toRefs(data), }}
  • ResourceList.vue

3.6 Vue 3.0 方法和计算属性

  • 利用方法实现列表数据的统计
  • ResourceHome.vue
{
{
getResourcesLength()}}
...// 列表数量统计方法const getResourcesLength = () => {
return data.resources.length}// 导出数据return {
getResourcesLength,}
  • 利用计算属性实现列表数据的统计
  • ResourceHome.vue
{
{
getResourcesLength()}}
...import {
computed } from 'vue';...// 列表数量统计(计算属性实现)const getResourcesLength = computed(() => {
return data.resources.length})

3.7 Vue 3.0 实现视图切换

  • 使用v-if/v-else实现视图切换

数据

...import {
ref } from 'vue';...// 3. 定义视图切换属性const isDetailView = ref(true)// 导出数据return {
isDetailView}

4. Vue 3.0 数据的交互

4.1 Vue 3.0 添加数据

  • ResourceHome.vue
...// 4. 添加数据事件const addResource = () => {
// debugger // 随机获取id const _id = "_" + Math.random().toString(36).slice(2) // 随机获取列表内容类型 const type = ["book","blog","video"][Math.floor(Math.random() * 3)] // 新的列表内容 const newResource = {
_id, title:`${
_id} title`, description:`${
_id} description`, link:'', type, } // 添加到数据列表前列 data.resources.unshift(newResource) }

4.2 Vue 3.0 调整样式

  • 修改切换按钮样式
  • ResourceHome.vue

数据

...// 5. 切换按钮样式const togglesBtnClass = computed(() => {
return !isDetailView.value ? "btn-primary" : "btn-warning"})
  • 修改数据列表固定高度
  • ResourceList.vue

4.3 Vue 3.0 选中数据显示详情

  • 选中ResourceList组件中的列表数据,将点击事件传入ResourceHome父组件
  • 从ResourceHome父组件传入ResourceDetail数据详情组件
  • ResourceList.vue
  • ResourceHome.vue
  • ResourceDetail.vue

4.4 Vue 3.0 选中状态

  • 选中列表数据改变其样式
  • ResourceList.vue

4.5 Vue 3.0 发送数据请求 axios

  • 安装 axios
    • npm install axis --save
  • ResourceHome.vue
// 生命周期钩子函数onMounted(async () => {
const resources = await fetchResources()});
  • index.js
import axios from 'axios'// 请求数据方法export function fetchResource(){
return axios.get("https://vue3-fjord-81553.herokuapp.com/api/resources")}

4.6 Vue 3.0 代理解决跨域

4.6.1 跨域问题
  • blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
4.6.2 跨域
  • 只要不同源,即为跨域
  • 同源策略: 以下任意一个不同,即为跨域
    • 协议头 http https file
    • 域名 baidu.com www.taobao.com
    • 端口号 8080 441 21 22
  • 域名不同 = 跨域
    • https://www.baidu.com:8888
    • https://www.taobao.com:8888
  • 协议不同 = 跨域
    • http://www.baidu.com:21
    • https://www.baidu.com:21
  • 端口不同 = 跨域
    • http://www.baidu.com:21
    • http://www.baidu.com:22
  • 同源
    • http://www.baidu.com:21
    • http://www.baidu.com:21/map/api/citi
4.6.3 解决跨域
  • jsonp

  • 服务器代理

  • 后端允许跨域

  • vue.config.js

module.exports = {
devServer: {
// 代理 proxy: {
"^/api": {
target: "https://vue3-fjord-81553.herokuapp.com", changeOrigin: true, }, }, },};

4.7 Vue 3.0 数据赋值

  • 请求接口数据
  • index.js
import axios from 'axios'// 请求数据方法export function fetchResources(){
return axios.get("/api/resources").then((res) => res.data)}
  • 数据赋值
  • ResourceHome.vue
// 生命周期钩子函数onMounted(async () => {
const resources = await fetchResources() data.resources = resources});

4.8 Vue 3.0 调整更新组件

  • ResourceUpdate.vue
  • ResourceHome.vue

4.9 Vue 3.0 watch 监听数据实时切换

  • 利用 watch 监听数据是否变化
  • ResourceUpdate.vue
import {
ref, watch } from 'vue'export default {
props: {
resource: Object }, setup(props, context) {
const uResource = ref(props.resource) watch( () => props.resource, (resource, prevResource) => {
uResource.value = resource } ) return {
uResource } }}

5. Vue 3.0 数据的处理

5.1 Vue 3.0 调整类型选项

  • ResourceUpdate.vue
...// 类型选项const types = ["blog","video","book"]

5.2 Vue 3.0 数据更新到服务器端

  • index.js
// 更新数据方法// 传入对应id,及新内容export function updateResource(id, resource){
return axios .patch(`/api/resources/${
id}`, resource) .then((res) => res.data)}
  • ResourceUpdate.vue
...import {
updateResource } from '@/actions'...// 提交事件(异步)const handleUpdate = async () => {
// 传入对应id和新内容 const updatedResource = await updateResource(uResource.value._id, uResource.value)}// 将更新的数据传给父组件context.emit("onUpdateResource", updateResource)
  • ResourceHome.vue
...// 8. 获取更新数据const handleUpdateResource = (newResource) => {
// 拿到原先存储数据的数组下标 const index = data.resources.findIndex( (resource) => resource._id === newResource._id ) data.resources[index] = newResource selectResource(newResource)}

5.3 Vue 3.0 弹窗提醒

  • ResourceUpdate.vue
{
{
alert.success }}
{
{
alert.error }}
...// 封装方法// 初始化弹窗状态const initAlert = () => {
return {
success: null, error: null }}// 弹窗状态const setAlert = (type, message) => {
data.alert = initAlert() data.alert[type] = message}// 提交事件(异步)const handleUpdate = async () => {
// 抛出异常 try {
// 传入对应id和新内容 const updatedResource = await updateResource( uResource.value._id, uResource.value ) // 将更新的数据传给父组件 context.emit("onUpdateResource", updatedResource) // 提交成功后弹窗信息 setAlert("success","Resource was updated") } catch (error) {
setAlert("error", error?.message) } }

5.4 Vue 3.0 设置定时器取消提醒

  • ResourceUpdate.vue
setup(props, context) {
// 接收数据 const uResource = ref(props.resource) // 类型选项 const types = ["blog","video","book"] // 弹窗信息 const data = reactive({
alert: {
success: null, error: null }, // 定义定时器 timeoutId: null }) // 监听数据切换 watch( () => props.resource, (resource, prevResource) => {
// 判断改变的值存不存在 if(resource && (resource._id !== prevResource._id)){
// 关闭定时器 clearAlertTimeout() data.alert = initAlert() } uResource.value = resource } ) // 封装方法 // 初始化弹窗状态 const initAlert = () => {
return {
success: null, error: null } } // 钩子函数 // 离开组件之前调用 onBeforeUnmount(() => {
// 清除定时器方法 clearAlertTimeout() }) // 清除定时器方法 const clearAlertTimeout = () => {
data.timeoutId && clearTimeout(data.timeoutId) } // 弹窗状态 const setAlert = (type, message) => {
data.alert = initAlert() data.alert[type] = message // 设置定时器 data.timeoutId = setTimeout(() => {
data.alert = initAlert() },3000) }}

5.5 Vue 3.0 删除数据

6. Vue 3.0 路由和搜索功能

6.1 Vue 3.0 配置路由

  • 安装路由
    • yarn add vue-router@next
  • router.js
import {
createRouter, createWebHistory } from "vue-router";import ResourceHome from "@/views/ResourceHome.vue";import ResourceNew from "@/views/ResourceNew.vue";const routes = [ {
path: "/", component: ResourceHome }, {
path: "/new", component: ResourceNew}];const router = createRouter({
history: createWebHistory(), // routes: routes, 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");

6.2 Vue 3.0 子级路由

  • router.js
import {
createRouter, createWebHistory } from "vue-router";import ResourceHome from "@/views/ResourceHome.vue";import ResourceNew from "@/views/ResourceNew.vue";import ResourceRoutes from "@/views/ResourceRoutes.vue"const routes = [ // ================================================================= // { path: "/", component: ResourceHome }, // { path: "/new", component: ResourceNew} // ================================================================= // 重定向、定义名字 // http://localhost:8080/resources // { // path: "/", // name: "base", // redirect: { name: "resourceHomePage"} // }, // { // path: "/resources", // name: "resourceHomePage", // component: ResourceHome // }, // { // path: "/resources/new", // name: "resourceNewPage", // component: ResourceNew // } // ================================================================= // 子路由 {
path: "/", name: "base", redirect: {
name: "resourceHomePage"} }, {
path: "/resources", name: "resourceHomePage", component: ResourceRoutes, children: [ {
path: "", name: "resourceHome", component: ResourceHome, }, {
path: "new", name: "resourceNewPage", component: ResourceNew, } ] }];const router = createRouter({
history: createWebHistory(), // routes: routes, routes,});export default router;

6.3 Vue 3.0 导航

  • Header.vue
首页
添加
  • router.js
import {
createRouter, createWebHistory } from "vue-router";import ResourceHome from "@/views/ResourceHome.vue";import ResourceNew from "@/views/ResourceNew.vue";import ResourceRoutes from "@/views/ResourceRoutes.vue"const routes = [ // 重定向、定义名字 // http://localhost:8080/resources {
path: "/", name: "base", redirect: {
name: "resourceHomePage"} }, {
path: "/resources", name: "resourceHomePage", component: ResourceHome }, {
path: "/resources/new", name: "resourceNewPage", component: ResourceNew }];const router = createRouter({
history: createWebHistory(), // routes: routes, routes, linkExactActiveClass: "active",});export default router;

6.4 Vue 3.0 重构更新组件

  • ResourceForm.vue
  • ResourceUpdate.vue

6.5 Vue 3.0 添加组件

  • ResourceNew.vue

6.6 Vue 3.0 详情跳转

  • ResourceDetailPage.vue

6.7 Vue 3.0 显示详情页面

  • ResourceList.vue

6.8 Vue 3.0 slot 插槽

  • ResourceDetail.vue
  • ResourceDetailPage.vue

6.9 Vue 3.0 搜索数据

  • ResourceSearch.vue
  • index.js
// 搜索功能export function searchResources(title) {
return axios.get(`/api/resources/s/${
title}`).then((res) => res.data);}

7. 总结

  • 新版 Vue 3.0 实战项目,做个笔记

转载地址:http://jcqwi.baihongyu.com/

你可能感兴趣的文章
python的collections
查看>>
J2ME程序开发新手入门九大要点
查看>>
双向搜索算法
查看>>
日本GAME製作方式
查看>>
移动行业术语资料
查看>>
3G到来将全面颠覆SP、CP游戏规则
查看>>
射击游戏中跟踪弹及小角度移动的开发
查看>>
播放声音文件的完整源代码
查看>>
J2ME编程最佳实践之灵活的RMS应用
查看>>
MOBILE FIRST: HOW TO APPROACH MOBILE WEBSITE TESTING? 移动优先:如何处理移动网站测试?
查看>>
开始使用Retrofit 2 HTTP 客户端
查看>>
对于初学者练习的6个开源项目
查看>>
保持冷静和需要打破的东西:软件测试初学者
查看>>
如何通过连接您的业务应用程序来节省时间
查看>>
熟悉现代JavaScript的培训计划
查看>>
7本书从小工到数据分析专家
查看>>
程序设计的基本原则:栈和堆
查看>>
Android应用程序架构
查看>>
Android:绘制自定义视图
查看>>
Android开发:一些有用的库(第一部分)
查看>>