若依框架前端Vue项目分析实战

news2025/2/27 21:15:49

说明

前面讲解了vue2的单点知识,下面用若依提供的vue项目,实战分析一下,拿到一个vue项目,如何进行分析并进行二次开发。

一、public/index.html与main.js和App.vue三者的关系

vue项目是单界面应用,所有的界面将在public下的index.html里呈现。
main.js是程序的入口,在这里,定义了vue实例对象。如下代码:

new Vue({
  el: '#app',
  router,//路由插件
  store,//vuex插件,所有的组件中都可以使用store中的action,mutation和state数据。通过$strore调用或者mapXXX函数映射
  render: h => h(App)
})

其中,el配置项是配置vm实例要填充的public/index.html里的元素对象。render属性配置的是用App.vue组件进行填充。在vm实例对象挂载完成之前,即mouted函数执行之前,页面显示的是public/index.html中本身的元素,在挂载完成后,public/index.html中会显示App.vue中的元素。
在public/index.html中,原有的是加载中插件,如下:

<body>
    <div id="app">
	    <div id="loader-wrapper">
		    <div id="loader"></div>
		    <div class="loader-section section-left"></div>
		    <div class="loader-section section-right"></div>
		    <div class="load_title">正在加载系统资源,请耐心等待</div>
        </div>
	</div>

所以,刷新界面时,先出现加载中界面,如下:
在这里插入图片描述
等vm实例挂载完成后,显示App.vue组件内容。

下面分析App.vue中组件的内容。
看template内容:

<template>
  <div id="app">
    <!-- 路由占位,router-link在哪   -->
    <router-view />
  </div>
</template>

这里只有router-view,说明这里要进行路由的切换展示。所以,接下来该分析路由的配置,看App.vue跳转到了哪个组件。

二、路由分析

路由的配置在router/index.js下,进行分析:

{
    path: '',
    component: Layout,
    redirect: 'index',
    children: [
      {
        path: 'index',
        component: () => import('@/views/index'),
        name: 'Index',
        meta: { title: '首页', icon: 'dashboard', affix: true }
      }
    ]
  }

这段路由配置就是App.vue挂载完成后的展示组件。首先,项目访问路径为’'(空)时,加载的组件是Layout组件,展示Layout组件内容。通过redirect属性重定向到index路径。index是子路由,在Layout中展示index.vue界面。这就是为何每次刷新,默认打开首页tab页的原因。
这里,补充个知识点:
不管是router-link的to属性,还是直接在浏览器输入路径,如果输入的是子路由的路径,那么界面会展示子路由的组件,也会展示父路由的组件。不会单独展示子路由对应的组件。
如:to=/home/SeatDistribute,则对应的view会显示App.vue和Home.vue和/home/SeatDistribute组件。
to=/home,view会显示App.vue组件和Home.vue组件。
根据路径,找router-view的位置:
路径为一层的,如:/home。则对应App.vue中的router-view。
路径为多层的,如/home/SeatDistribute,则找其父组件的router-view,即Home.vue组件中的router-view。

所以,上面重定向到index.vue组件后,也是显示Layout组件的。即在Layout组件内部,再显示index.vue组件。router定义子路由时,默认children子路由就是被父路由包裹的。

三、Layout组件分析

通过上面分析,可知App.vue展示的是Layout组件,那么下面就分析Layout组件。通过分析,Layout组件是布局组件,即后台管理系统的整体布局,是通过这个组件完成的。里面包含了很多子组件嵌套。下面先画一下其组件划分结构:
在这里插入图片描述
可见,将整体布局划分成上图的几个组件。这也体现出了vue组件化编程的思想。在每个组件内部,又对各个部分进行了组件的拆分,例如在navbar组件中,
在这里插入图片描述
每个元素,都划分成了一个组件。这里主要体会组件化编程思想。具体组件的实现方式,这里不做深入研究。已经提供好的功能,我们直接拿来用即可。

四、Vuex应用分析

在main.js中定义vue的时候,可以看到使用了Vuex技术,如下:

new Vue({
  el: '#app',
  router,//路由插件
  store,//vuex插件,所有的组件中都可以使用store中的action,mutation和state数据。通过$strore调用或者mapXXX函数映射
  render: h => h(App),
  beforeMount() {
    debugger;
  }
})

下面就分析一下Vuex技术在项目中是如何应用的。
首先,看stroe/index.js文件:

Vue.use(Vuex)

const store = new Vuex.Store({
  modules: {
    app,
    user,
    tagsView,
    permission,
    settings
  },
  getters
})

export default store

可以看到,使用了模块化命名,分成了权限模块,设置模块,用户模块等几个模块。因为Vuex最终操作的都是state对象,所以,重点看一下这几个模块的state对象都存入了什么:
权限模块permission.js:

state: {
    routes: [],
    addRoutes: [],
    defaultRoutes: [],
    topbarRouters: [],
    sidebarRouters: []
  }

可见,权限模块state存入了路由数据。路由可以共享到每个组件去使用。

用户模块user.js:

state: {
    token: getToken(),
    name: '',
    avatar: '',
    roles: [],
    permissions: []
  }

用户模块state定义了token,用户名,用户角色,用户权限等数据,用于共享。

设置模块settings.js:

const state = {
  title: '',
  theme: storageSetting.theme || '#409EFF',
  sideTheme: storageSetting.sideTheme || sideTheme,
  showSettings: showSettings,
  topNav: storageSetting.topNav === undefined ? topNav : storageSetting.topNav,
  tagsView: storageSetting.tagsView === undefined ? tagsView : storageSetting.tagsView,
  fixedHeader: storageSetting.fixedHeader === undefined ? fixedHeader : storageSetting.fixedHeader,
  sidebarLogo: storageSetting.sidebarLogo === undefined ? sidebarLogo : storageSetting.sidebarLogo,
  dynamicTitle: storageSetting.dynamicTitle === undefined ? dynamicTitle : storageSetting.dynamicTitle
}

可见,settings.js模块定义了皮肤颜色,主题风格,边距等等数据用于共享。

各模块的Actions和Mutations对象定义了各种函数来操作这些state数据,这里就 不一一列举了。

通过上面存入Vuex中的数据可以知道,在项目中,把全局的一些信息,存入Vuex中。这些信息可以是前端自己设定的,也可以是后台获取的数据。这样,在项目的任何一个组件中,都可以通过$store属性或者mapXXX函数获取到这些共享数据。
Vuex有点儿类似于原生js中的全局变量的感觉。

五、关于动态路由和菜单权限的实现

前面讲路由时,路由都是在router/index.js里预置好的。但是在真实项目中,菜单肯定是通过权限,在后台获取的。分析一下若依框架,是如何实现权限分配和动态路由的。
首先找到菜单的组件,上面已经分析过,是Layout组件中的sidebar组件。点进去,看sidebar组件的实现:

<sidebar-item
                    v-for="(route, index) in sidebarRouters"
                    :key="route.path  + index"
                    :item="route"
                    :base-path="route.path"
                />

可见,其遍历了sidebarRouters,而sidebarRouters通过Vuex的分析可知,其配置在了permissions模块的state中。所以,在permissions.js的Actions对象和Mutations对象中,肯定有操作这个数据的函数,找相应的代码。
代码比较分散,下面看其实现思路:
首先,在Actions函数中,利用axios发送请求到后台,获取用户菜单权限,该接口的返回值如下:

{
	"msg": "操作成功",
	"code": 200,
	"data": [{
		"name": "System",
		"path": "/system",
		"hidden": false,
		"redirect": "noRedirect",
		"component": "Layout",
		"alwaysShow": true,
		"meta": {
			"title": "系统管理",
			"icon": "system",
			"noCache": false,
			"link": null
		},
		"children": [{
			"name": "User",
			"path": "user",
			"hidden": false,
			"component": "system/user/index",
			"meta": {
				"title": "用户管理",
				"icon": "user",
				"noCache": false,
				"link": null
			}
		}, {
			"name": "Role",
			"path": "role",
			"hidden": false,
			"component": "system/role/index",
			"meta": {
				"title": "角色管理",
				"icon": "peoples",
				"noCache": false,
				"link": null
			}
		}, {
			"name": "Menu",
			"path": "menu",
			"hidden": false,
			"component": "system/menu/index",
			"meta": {
				"title": "菜单管理",
				"icon": "tree-table",
				"noCache": false,
				"link": null
			}
		}, {
			"name": "Dept",
			"path": "dept",
			"hidden": false,
			"component": "system/dept/index",
			"meta": {
				"title": "部门管理",
				"icon": "tree",
				"noCache": false,
				"link": null
			}
		}, {
			"name": "Post",
			"path": "post",
			"hidden": false,
			"component": "system/post/index",
			"meta": {
				"title": "岗位管理",
				"icon": "post",
				"noCache": false,
				"link": null
			}
		}, {
			"name": "Dict",
			"path": "dict",
			"hidden": false,
			"component": "system/dict/index",
			"meta": {
				"title": "字典管理",
				"icon": "dict",
				"noCache": false,
				"link": null
			}
		}, {
			"name": "Config",
			"path": "config",
			"hidden": false,
			"component": "system/config/index",
			"meta": {
				"title": "参数设置",
				"icon": "edit",
				"noCache": false,
				"link": null
			}
		}, {
			"name": "Notice",
			"path": "notice",
			"hidden": false,
			"component": "system/notice/index",
			"meta": {
				"title": "通知公告",
				"icon": "message",
				"noCache": false,
				"link": null
			}
		}, {
			"name": "Log",
			"path": "log",
			"hidden": false,
			"redirect": "noRedirect",
			"component": "ParentView",
			"alwaysShow": true,
			"meta": {
				"title": "日志管理",
				"icon": "log",
				"noCache": false,
				"link": null
			},
			"children": [{
				"name": "Operlog",
				"path": "operlog",
				"hidden": false,
				"component": "monitor/operlog/index",
				"meta": {
					"title": "操作日志",
					"icon": "form",
					"noCache": false,
					"link": null
				}
			}, {
				"name": "Logininfor",
				"path": "logininfor",
				"hidden": false,
				"component": "monitor/logininfor/index",
				"meta": {
					"title": "登录日志",
					"icon": "logininfor",
					"noCache": false,
					"link": null
				}
			}]
		}]
	}, {
		"name": "Monitor",
		"path": "/monitor",
		"hidden": false,
		"redirect": "noRedirect",
		"component": "Layout",
		"alwaysShow": true,
		"meta": {
			"title": "系统监控",
			"icon": "monitor",
			"noCache": false,
			"link": null
		},
		"children": [{
			"name": "Online",
			"path": "online",
			"hidden": false,
			"component": "monitor/online/index",
			"meta": {
				"title": "在线用户",
				"icon": "online",
				"noCache": false,
				"link": null
			}
		}, {
			"name": "Job",
			"path": "job",
			"hidden": false,
			"component": "monitor/job/index",
			"meta": {
				"title": "定时任务",
				"icon": "job",
				"noCache": false,
				"link": null
			}
		}, {
			"name": "Druid",
			"path": "druid",
			"hidden": false,
			"component": "monitor/druid/index",
			"meta": {
				"title": "数据监控",
				"icon": "druid",
				"noCache": false,
				"link": null
			}
		}, {
			"name": "Server",
			"path": "server",
			"hidden": false,
			"component": "monitor/server/index",
			"meta": {
				"title": "服务监控",
				"icon": "server",
				"noCache": false,
				"link": null
			}
		}, {
			"name": "Cache",
			"path": "cache",
			"hidden": false,
			"component": "monitor/cache/index",
			"meta": {
				"title": "缓存监控",
				"icon": "redis",
				"noCache": false,
				"link": null
			}
		}]
	}, {
		"name": "Tool",
		"path": "/tool",
		"hidden": false,
		"redirect": "noRedirect",
		"component": "Layout",
		"alwaysShow": true,
		"meta": {
			"title": "系统工具",
			"icon": "tool",
			"noCache": false,
			"link": null
		},
		"children": [{
			"name": "Build",
			"path": "build",
			"hidden": false,
			"component": "tool/build/index",
			"meta": {
				"title": "表单构建",
				"icon": "build",
				"noCache": false,
				"link": null
			}
		}, {
			"name": "Gen",
			"path": "gen",
			"hidden": false,
			"component": "tool/gen/index",
			"meta": {
				"title": "代码生成",
				"icon": "code",
				"noCache": false,
				"link": null
			}
		}, {
			"name": "Swagger",
			"path": "swagger",
			"hidden": false,
			"component": "tool/swagger/index",
			"meta": {
				"title": "系统接口",
				"icon": "swagger",
				"noCache": false,
				"link": null
			}
		}]
	}, {
		"name": "Http://ruoyi.vip",
		"path": "http://ruoyi.vip",
		"hidden": false,
		"component": "Layout",
		"meta": {
			"title": "若依官网",
			"icon": "guide",
			"noCache": false,
			"link": "http://ruoyi.vip"
		}
	}]
}

分析其返回值,可以看到,就是按照router的格式,将菜单数据进行了返回。其中,子菜单就以children属性,定义在了父菜单下面。菜单名称,定义在了meta属性里面。
这样,就根据用户权限获取了菜单路由信息。下面,看这些信息是如何进行使用的。
还回到Sidebar组件的这段代码:

 <sidebar-item
                    v-for="(route, index) in sidebarRouters"
                    :key="route.path  + index"
                    :item="route"
                    :base-path="route.path"
                />

可以看到,涉及到另一个自定义组件sidebar-item,遍历菜单,把获取到的路由信息传了过去,最终实现了菜单的展示和点击出现tab页面。具体实现不再详细解释。

六、自定义指令的应用

若依框架自定义了几个指令,下面看如何进行自定义指令和这几个指令的作用:
在directive包下,进行了自定义指令。
重点看permissions相关的自定义指令。一个权限指令,一个角色指令,其实现思路就是根据Vuex中user的角色和权限数据,判断是否有某个角色或者某个权限,从而判断是否有权限操作某个按钮。即菜单中按钮权限的判断,是通过自定义指令完成的。

七、关于element-ui

在一个组件中,有很多的标签,当是el-开头的时候,就是element-ui的标签,可以根据官网查找对应属性的意思等。不是以el开头的标签,可能是项目自定义的组件,也可能是第三方组件。具体的点进去一看便知。

八、history模式与项目部署

前面讲到,history模式下,刷新浏览器,会报404,这里,再说清楚一点。
在开发环境中,即使使用history模式,刷新界面,不会报404,但是项目打包部署到web服务器上后,再访问前端项目,再刷新界面,会报404,这是为何呢?
个人理解,在开发环境中,vue-cli自行解决了history刷新报404的问题,直接通过路由,定位到了相应的组件。但是项目部署到web服务器上后,刷新界面,浏览器中的url直接就发送到web服务器上了,服务器默认并不会处理路径,而是直接根据路径找资源,找不到url的资源,所以就报404了。
项目部署后,如何解决history模式的404问题呢?根据不同的web服务器,进行简单的设置,就可以解决了。
具体可参考:不同的历史模式
下面记录在nginx下部署vue项目的过程。
首先,在package.json中, 运行build命令,对项目进行打包。
打包完成后,在项目根目录下,会生成dist文件,dist文件里,打包好的文件,有个index.html文件,整个vue项目,就在这个单界面里展示。

配置nginx服务器:
首先,配置nginx.config配置文件,重点如下:

server {
        listen       80; #nginx端口,也是前端项目访问的端口
        server_name  localhost;#nginx的ip,也是前端工程访问ip

        #charset koi8-r;

        #access_log  logs/host.access.log  main;

        location / {
            root   "F:/java_structure/vue/RuoYi-Vue-master/ruoyi-ui/dist";#vue项目打包dist后的路径
            index  index.html index.htm;#这里配置index就行,不用管
			try_files $uri $uri/ /index.html;#解决history刷新报404问题,配置此项后刷新就不再报404了。
        }
		#vue项目想后台发送请求的前缀。在开发环境中,配置proxyTable可以进行代理转发。在nginx上,在此进行代理转发配置
		location ^~/prod-api { 
		   rewrite ^/prod-api/(.*)$ /$1 break; #此配置表明发送到后台的请求不带prod-api,将其自动去掉
           proxy_pass http://localhost:8080; #后台服务器路径。此处需要注意,这里的后台服务器,是为vue项目提供数据支撑的服务器。而上面配置的listen和server_name,是nginx的port和ip,也是前端项目的port和ip。解决history模式404的问题,也是解决的nginx服务器返回的404的问题,并不是解决后台项目返回的404的问题,这点一定要清楚。
        }

        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }
    }

八、统计图,报表使用

echarts可以和vue很好的配合使用,此外,再提供一个很好的统计报表可视化插件库:Viser

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/405144.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

VSCode 入门操作大全 + 实用插件推荐【零基础专属详细教程】

&#x1f4c0; 前言&#xff1a; &#x1f3ab; 选择一个好的开发工具很重要&#xff0c;很多刚学编程的小伙伴在 webstorm 和 vscode 上很难抉择&#xff0c;我个人更喜欢使用 vscode&#xff0c;因为其有着简洁的操作风格和丰富的人性化的各种功能&#xff0c;这篇文章带给大…

2022年前端Vue常见面试题大全(三万长文)持续更新...

目录 1.Vue和React有什么不同&#xff1f;使用场景分别是什么&#xff1f; 2.axios是什么&#xff1f;怎么使用它&#xff0c;怎么解决跨域&#xff1f; 3.说说Vue&#xff0c;React&#xff0c;angularjs&#xff0c;jquery的区别 4.什么阶段&#xff08;生命周期&#xff…

2022最新版40个前端练手项目【附视频+源码】

不管学习哪门语言都希望能做出实际的东西来&#xff0c;这个实际的东西当然就是项目啦&#xff0c; 不用多 说&#xff0c;大家都知道学编程语言一定要做项目才行。 本次给到大家的是40个前端实战练手项目(附源码和视频讲解)&#xff0c;希望对大家有一定的帮助&#xff0c;激…

企微获取用户敏感数据

1、企微配置可信域名 2、企微获取成员userID 3、企微获取用户敏感数据 文章目录一、简介1、企微数据安全更新2、身份验证方式2.1 网页授权登录(企微内部)2.2 扫描授权登录(浏览器)二、企微应用配置1、企微配置可信域名2、企微授权登录3、企微可信IP三、网页授权登录方式(企微)1…

Vue2 大型项目升级 Vue3 详细经验总结

前言 前段时间&#xff0c;公司准备在现有的 Vue2 项目中做一个聊天系统&#xff0c;但考虑开发聊天系统的周期并不短&#xff0c;客户又急需。于是准备对接腾讯的 IM 组件&#xff0c;来实现。 不知道的这里贴个官网&#xff1a; IM TUIKit 官方文档 对于 TUIKit&#xff0…

【axios】axios的基本使用

axios是一个专注于网络请求的库。 不同于jquery&#xff0c;功能复杂&#xff0c;既可以操作dom&#xff0c;又可以做动画&#xff0c;还可以发ajax请求。axios是一个专注于网络请求的库。 一、基本使用 1.导入库文件 在js中导入axios的库文件后&#xff0c;会直接在全局挂载…

[vue 进阶] 关于dicts字典的用法

最近在学习若依系统的框架&#xff0c;其中发现一个很奇怪的事情&#xff0c;网上查询很多地方&#xff0c;也是一知半解。 网上搜索的结果如下&#xff0c;大家可以先看看&#xff1a; [vue 进阶] 关于dicts字典的用法_小钿钿不忘初心_的博客-CSDN博客前言在使用若依框架开发…

CSS3如何调整背景图片大小

系列文章目录 CSS3实现半透明边框&#xff08;1&#xff09; CSS3实现多重边框&#xff08;2&#xff09; CSS3如何改变背景图片大小系列文章目录一、background-size语法格式二、参数详解1.length2.percentage3.cover4.contain总结在CSS3中&#xff0c;如果想要调整背景图片的…

适合普通大学生的前端开发学习路线

大家好&#xff0c;我是帅地。 假如你没有明确的目标&#xff0c;或许可以按照我说的学习路线来学习一波&#xff0c;我写的每一份学习路线&#xff0c;不会很全面&#xff0c;因为我认为&#xff0c;东西列的太多&#xff0c;反而不利于新手的学习&#xff0c;所以我列举的&a…

Vue中的路由

目录 目录 一&#xff0c;路由理解 二&#xff0c;基本配置 第一步: 在main.js文件中引入并使用插件 第二步: 在src文件夹下创建一个router文件夹然后在文件夹下创建index.js ​编辑 第三步: 回到main.js中引入创建的 router 并在vue实例对象中使用 三&#xff0c;路由的…

vue使用富文本编辑器vue-quill-editor

问题描述&#xff1a; 我们在开发过程中经常会遇到使用富文本编辑器进行操作&#xff0c;当前插件市场上关于富文本的编辑器挺多的&#xff0c;我们就不一一个介绍了&#xff0c;现在我们主要讲解一些vue-quill-editor富文本编辑器的使用操作和注意事项。 效果图 具体操作使用…

是什么让学习 Web 开发在未来几年变得有价值?

&#x1f482; 个人网站:【海拥】【摸鱼游戏】【神级源码资源网】&#x1f91f; 前端学习课程&#xff1a;&#x1f449;【28个案例趣学前端】【400个JS面试题】&#x1f485; 想寻找共同学习交流、摸鱼划水的小伙伴&#xff0c;请点击【摸鱼学习交流群】&#x1f30a; 本文首发…

React中ref的使用方法和使用场景(详解)

摘要 不管在Vue中还是React&#xff0c;如果我们想使用一个元素的DOM&#xff0c;不需要通过JS中操纵DOM的方法&#xff0c;它们提供了一个专属的API就是ref。 而Vue中的ref可能比较简单&#xff0c;这一篇主要讲一下如何在React中使用ref&#xff0c;以及使用ref的场景。 1…

如何创建vue3项目

目录 如何创建vue3项目 1、用vue cli创建 2、使用vite直接创建 3、使用vue3官方推荐创建方式 如何创建vue3项目 创建vue3我们常用的有三种方式&#xff1a; 1、用vue cli创建 1.使用vue cli环境前提条件&#xff1a; node -vv16.13.0 npm -v8.1.0 vue -Vvue/cli 4.5.15 …

微信小程序中使用vant组件库(超详细)

目录前言Vant Weapp的安装与使用1、安装 node.js2、通过 npm 安装3、修改 app.json4、修改 project.config.json5、构建 npm 包6、使用组件全局引入和局部引入全局引入局部引入Toast 组件的使用官方文档 API 详解Props 参数Events 事件Slot 插槽外部样式类前言 Vant是一个轻量…

vue中this.$router.push()路由传值和获取的两种常见方法

今天接到了比较大的需求&#xff0c;由于这个公司的接口调用方法和上一段实习那家公司的写法很不一样&#xff0c;我花了很多时间在摸索&#xff0c;“踏出第一步总是最困难的”&#xff0c;果然没错&#xff0c;第一个很费劲&#xff0c;但完成之后有了思路&#xff0c;下面的…

登录功能的实现(包括前后端)

目录:&#x1f349;&#x1f349;&#x1f349;UPDATE:✨✨✨前言✨✨✨概述✨✨✨技术栈✨✨✨效果图✨✨✨代码✨✨✨github链接&#x1f349;&#x1f349;&#x1f349;UPDATE: 突然发现喜提榜一&#xff0c;蟹蟹读者老爷们的支持(づ&#xffe3; 3&#xffe3;)づ 润色了…

微信小程序完整项目实战(前端+后端)

基于微信小程序的在线商城点单系统 前言&#xff1a;闲来无事&#xff0c;想以后自己开一个小超市或者小吃店&#xff0c;能够支持线上下单&#xff0c;既方便客户也方便自己。系统采用C#语言作为后端实现与小程序的交互&#xff0c;给用来学习或者想自己开个小店的朋友当个参考…

如何在 WordPress 中嵌入 iFrame

&#x1f482; 个人网站:【海拥】【摸鱼游戏】【神级源码资源网站】&#x1f91f; 前端学习课程&#xff1a;&#x1f449;【28个案例趣学前端】【400个JS面试题】&#x1f485; 想寻找共同学习交流、摸鱼划水的小伙伴&#xff0c;请点击【摸鱼学习交流群】&#x1f4ac; 免费且…

【uniapp小程序开发】—— 组件封装之【自定义轮播图】

文章目录&#x1f34b;前言&#xff1a;&#x1f34d;正文1、首先了解swiper组件1.1、小小的demo示例&#xff1a;1.2、自定义轮播图效果展示说明2、完成自定义轮播图效果3、组件封装——自定义轮播图3.1、创建swiper-doc.vue组件3.2、组件调用&#xff0c;封装完成&#x1f38…