ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Vue开源项目学习一

2022-02-21 20:58:00  阅读:130  来源: 互联网

标签:Vue 封装 可以 学习 开源 切换 组件 监听 首页


Vue项目开发一

  1. 划分目录结构

    — 通过vue create my_ProjectVueCLI3创建项目!

    —目录结构:

    (1)src/assets:资源目录,放置图片、CSS样式文件等资源;可以分别建立两个文件夹images和css文件目录,用于存放图片和css文件!

    (2)src/components:组件目录,放置各种组件,但是如果将所有的组件都放置里面,会十分混乱,因此可以在src下再创建一个views文件夹,将不同的视图组件放置里面,而components中主要放置公共组件;同时可以在components中细分为两类common和content,common中放置的不仅仅为该项目下,还可以直接被其他项目所复用的组件;content只放置与当前项目业务相关的组件,不可被其他项目所复用;

    (3)src/router:路由目录,放置路由相关的文件;

    (4)src/store:vuex状态管理目录;

    (5)src/network:网络请求相关所有的封装目录;

    (6)src/common:公共的js文件目录,可以将所有的公共常量抽取放置于该目录下的const.js文件中;也可以封装一些工具类放置在utils.js中;

  2. CSS文件的引入

    —为了保持CSS样式一致性,我们通常需要引用第三方normalize.css文件进行样式统一,参考网址:https://github.com/necolas/normalize.css

    —除了引用第三方的css文件,我们也可以自己建一个base.css文件,然后通过@import "./normalize.css"引入当前base.css文件下;同时通过@import "./assets/css/base.css"将base.css引入到App.vue的<style>标签下;

    CSS相关知识

    可以在css文件夹下通过伪类选择器:root获取根元素html,并且在该伪类选择器中定义变量:

    :root{--large-size:14px;},然后可以在其他样式设置中通过var(--large-size)的形式进行引用;

  3. vue.config和editorconfig配置文件

    VueCLI3中配置别名:

    —首先自己在项目目录(根目录)下创建一个vue.config.js文件;

    —然后在文件下通过module.exports = {}进行别名配置:

    module.exports = {
    configureWebpack:{
      extension:['.js','.vue','.json'],
      resolve:{
          //配置别名
          alias:{
              '@':'src',
              'assets':'@/asstes',
              'common':'@/common',
              'components':'components',
              'netwok':'@/network'
          }
      }
    }
    }
    

    —这里可以不用配置router和store,因为它们可以通过this.$routerthis.$store进行引用;

    —这里需要注意,当我们通过import引入路径时,通过上述别名配置无问题,但是当在标签中通过HTML的src属性中引用路径,需要在路径前加入~符号;

    采用VueCLI2创建项目的过程,默认会生成一个.editorconfig文件,这个文件会对代码风格进行统一,比如缩进大小等;在VueCLI3中是没有这个文件的,因此我们可以将.editorconfig文件拷贝到自己项目下,进行项目代码风格的统一;

  4. 底部导航条封装

    项目需求:底部导航可以根据用户自定义内容,并且点击导航条内容,可以跳转到对应页面下;

    项目实现

    —因为tabbar这个业务可以供多个项目进行复用,将其放在components/common/tabbar下;

    —因为tabbar涉及到路由映射管理,因此需要安装路由:npm install vur-router --save;安装完毕在router文件夹下创建index.js文件进行路由配置和导出,并在main.js中挂载router

    —项目模块划分完成tabbar和路由映射关系的配置;

    另外可以在public目录下的index.html文件下<link>修改网页的图标;

    —这里通过<%= BASE_URL %>获取当前文件所在的路径,可以动态的获取路径,jsp语法;

    tabbar项目的创建思路:封装一个TabBar作为底部导航条的最外层容器,容器内的内容不是固定的,用户可以自定义设置,所以定义插槽,动态添加内容;并且底部导航条的内容可以细分为多个不同的子部分,对每个子部分进行封装为TabBarItem,同时使用具名插槽动态添加图片和文字;可以将以上两个组件进一步封装为一个组件MainTabBar;

    项目相关问题

    (1)我们在使用插槽的时候,一般会在最外层包装一层容器,因为插槽会被完全替换,则我们绑定在插槽的属性会被替换掉而无法显示,所以如果进行插槽相关的属性设置,通常在外层包装一层容器div

    (2)点击响应事件:该操作下,不仅对应的点击的DOM元素样式需要变换,而且还要跳转到对应的网页,这里涉及到路由路径跳转问题;

    样式变换:图片变换,我们可以再添加一个具名插槽,当被点击激活时,该具名插槽下的图片显示,否则显示原始图片;可以通过v-ifv-else控制图片的显示;文字颜色变换,我们可以对文字颜色变换进行封装,用户可以自定义变换颜色,只需要在使用我们封装的组件时传入颜色参数即可,通过props可以获得父组件的数据(用户自定义数据),并在computed属性中进行动态绑定属性:style实现文字样式切换;

    路由路径跳转:一般在较大项目中,像我们需要通过不同路由切换不同页面,我们可以将这些独立组件放置在./src/pages或者叫做views下(便于分组管理),components文件夹下一般放置公共组件;因为路由跳转并不是固定值,我们在点击时,由父组件 传入跳转路由路径,并且通过props获取路径,在methods设置监听事件,通过this.$route.replace(this.path)跳转相关页面;如果跳转页面还能返回原来页面,就使用push进行路由跳转;

    如何动态的获取激活状态:获取当前处于活跃的路由是否与当前路径一致,this.$router.path.indexOf(this.path) !==-1

  5. 首页视图的顶部导航条封装

    —项目需求:可以自定义导航条内容,主要分为左右中三部分;

    项目实现

    —顶部导航条可以在不同的项目下进行复用,因此我们可以将其放在compnoents/common下;

    —使用具名插槽便于用户插入自定义内容,并且在外层添加一个容器包裹;

    —可以在当前组件设置相关导航样式,这里的样式一般是公共样式,常用样式display:flex设置弹性盒样式以实现子内容的均分排列;

    —只需要在用到顶部导航的页面下导入导航组件即可,并且可以在当前页面下设置私有的导航CSS样式;

  6. 首页视图轮播图封装

    —项目需求:首页视图下,请求服务器数据,并以轮播图的形式展现;

    项目实现

    —在进行轮播图的创建时,必须要将数据请求过来,因此需要用到网络请求模块axios;

    —这里需要注意:为了避免网络请求模块和首页的高度耦合度,我们对网络请求进行封装,增加一个模块 ,这样当前开发的网页只需要面向我们封装的模块实现网络请求,并且一个网页可能有多个网络请求,方便统一管理页面的网络请求!!我们只需要导入封装的网络请求函数即可在首页完成网络请求;

    —网络请求模块一般在组件创建完毕即引入,因此在生命周期函数created()中导入网络数据请求函数;一定要注意,需要个变量完成网络请求数据的保存,因为函数调用(压入函数栈,保存函数调用过程中所有的变量,临时的),当函数调用结束后,弹出函数栈,释放函数中所有的变量,因此我们需要将其保存在一个变量中,以防止函数调用完毕后,数据被释放;另外,网络请求是异步操作模块;

    —轮播图组件的封装:(待添加)将轮播图封装为一个组件,使得Home.vue简洁清晰;

    —轮播图请求的数据是首页请求的,因此我们需要通过props将父组件的数据传入轮播图组件中以便于实现轮播图;

    —根据网络响应的数据通过v-for循环遍历swiperItem的数量;预留了插槽,只需要在插入网络请求的轮播数据即可,a标签下的跳转链继和图片内容都封装在轮播数据中;

  7. 首页推荐栏的封装

    —项目需求:推荐栏分别展示商品和标题内容;

    项目实现

    —这里需要从父组件网路请求的数据中通props过获取数据;

    —直接在组件中封装图片和文字,并通过v-for遍历请求数据项的数目,将请求的图片和文字添加到a链接中;

    —直接在组件下设置样式相关CSS样式;

  8. 首页中本周流行栏的封装

    —项目需求:这里设计简单,只是将一张图片放在流行栏中展示;

    项目实现

    —只需要在组件下将图片插入a标签下,并在Home.ve导入挂载组件即可;

  9. 首页中切换栏内容封装

    —项目需求:点击切换项,首页展示不同切换项下的商品和信息

    项目实现

    —切换栏切换效果实现

    —这个组件可以在其他页面进行复用,我们可以封装在components/content目录下;

    —切换栏样式在不同页面下只是文字内容不同,尽量避免使用插槽,并且文字内容是父组件在调用过程中用户自定义传入的,通过props进行访问和v-for填充文字内容;

    —设计选中文字时的状态,绑定class属性,并设置监听点击事件响应函数itemClick,通过判断当前点击切换项的索引值是否与切换项索引值(v-for下获取的index值)相等,改变选中文字的状态::class = {active:index === currentIndex}

    —设置文字选中状态这里我们为了项目开发方便,可以在公共base.css文件下通过伪类选择器获取根元素,然后设置相关变量,并通过var(变量名)的形式进行样式设置;

    —CSS样式相关:根据项目需求,可以在调用该切换栏的组件下,给该组件设置样式:position:sticky粘性定位,使得当滚动到某个位置(可自定义值)时,切换栏的定位变为fixed;这个属性部分浏览器不支持;因此不建议使用该种方法;

    切换栏的吸顶效果

    【1】可以根据滚动位置将切换栏进行固定,形成吸顶效果;首先需要获取到切换栏的offsetTop大小,这里我们在首页组件下通过$refs获取到的只是组件,并不是DOM元素,无法直接得到offset值,所有组件都有一个$el属性,用户可以获取组件内的元素,因此可以通过$refs.refName.$el.offsetTop获得当前滚动高度;另外要注意,在mounted函数下,获取的高度只是图片未加载的高度,因此offsetTop值并不准确,因此这需要我们等到图片加载完成后,才可以计算offsetTop高度;

    【2】这里设计简单,只考虑轮播图片加载完成,其他图片加载速度较快,影响不大;在轮播图组件下设置图片加载监听事件,并传递到首页组件下(这里不需要事件总线,因为它们两个是父子组件);在首页下进行监听调用,当图片加载完毕后,获取其offsetTop值;另外,这里发送事件会根据轮播图数量的多少进行发送,因此我们可以进行一次判断,设置一个isLoad值默认为false,进入加载图片的判断和发送事件,然后将isLoad改为true,这样只发送一次事件,后续不会在调用发送事件了;

    【3】监听滚动,动态改变切换栏样式,之前我们在进行返回顶部的时候,已经完成监听滚动事件,可以在其下进行切换栏的吸顶效果(position:fixed);设置一个数据值isFixed,默认是fasle,并在滚动监听函数下判断滚动位置是否大于切换栏的滚动高度,然后绑定class属性完成吸顶效果设置;经验证,行不通!下面商品内容会突然上移,并且切换栏虽然设置了fixed,但是也会跟着Better-scroll一起滚动;

    【4】另一种实施方案hack方案,复制一份切换栏组件对象放在顶部导航条下,利用它实现停留效果;设置定位层级,将其显示在最高层,通过v-show默认是不显示,当滚动到切换栏位置下将其显示出来;一般在项目开发中常使用这种方案,另外这里需要注意,新复制的切换组件要和之前组件点击事件后,请求到的数据保持一致,以便于实现切换栏下的数据在对应的点击项中是一致的;

    —切换栏商品内容展示效果

    设计商品数据结构:向服务器端请求全部商品数据,但是我们在使用数据的时候,需要设计数据结构以便于在切换栏中不同切换项下显示;

    商品数据结构:首先请求的数据设置为对象格式,包括多个切换项的数据;每一个切换项的数据格式也是一个对象,保存的是一个切换项下页面和当前页面下加载的商品数组;可以将默认的商品数据结构放在Home组件的data()中;

    网络请求数据:这里我们可以将全部的网络请求包装在methods中,直接在生命周期函数created中调用封装好的请求函数,避免全部的网络请求函数具体实现代码在created()中,不便于管理;设计网络请求函数,动态传入两个参数,当前切换项type和当前切换项下所加载的页数page;另外通过push函数和扩展操作符...完成当前切换项商品数据数组的拼接;

    商品数据的展示:封装一个大组件,大组件下放置多个子组件项,子组件项中进行商品数据展示;首先我们需要在大组件下通过props获取首页请求的商品数据,根据获取的数据大小决定子组件的数量并通过子组件进行展示;我们子组件同时需要通过props拿到父组件遍历的数据项以便于展示商品;可以在首页computed下创建展示函数,将当前切换项的数据进行展示:this.goods[currentType].list

    点击切换效果:需要完成在点击切换项时,商品展示也进行切换;之前我们已经在切换导航中设置了监听点击响应事件,这里需要将切换栏的点击事件通过自定义事件this.$emit('tabClick',index)传到首页父组件中,并在首页中@tabClick进行调用,这里点击事件将当前切换项的索引index传出来,我们可以根据切换索引通过switch建立索引和切换项之间的映射关系,做出相应的商品切换;

  10. 滚动条和Better-Scroll的使用

—项目需求:由于原生滚动条容易产生卡顿,安装使用开源的滚动条模块

项目实现

—在该项目的开发中,由于内容居多需要使用到滚动条,但是原生的滚动条滑动会卡顿,我们可以进行安装别人开发好的滚动条模块:github上的iscroll开源模块(但是是现在不在维护)、因此可以使用better-scroll;

—另外如果在开发项目过程中,想要搜索某个模块的原生代码,可以去GitHub上在Tag中找到最新版本下的dist文件夹,里面存储着是原生代码;

—安装better-scrollnpm install better-scroll --save

better-scroll在使用过程中的官方要求:需要在最外层包裹一个有固定高度的父元素wrapper,并且父元素下只能有一个容器content,这样可以实现局部滚动;

better-scroll封装:另外在开发项目过程中,尽量不要过分依赖better-scroll以避免过于耦合,因此我们可以对better-scroll进行封装,以方便后续开发中如果遇到问题,避免大量页面重构修改;另外我们可以封装成可以自定义滚动条特性的组件,需要用户自定义传入参数probeType(定义是否滚动监听)和pullUpLoad(是否上拉加载更多监听),因此我们可以在封装的滚动条上通过pros进行获取用户自定义的参数值;

元素查询方式:一般在Vue中进行元素查询需要通过ref的方式,ref如果绑定在组件上,通过this.$refs.refName获取的是该组件对象;ref中绑定在一个DOM元素上,通过this.$refs.refName所获取的就是该DOM元素;而通过document.querySelector获取的DOM元素是页面中第一个DOM元素,有时候与我们的目标元素不符;

—滚动区域大小计算:一种方法是可以通过calc()进行滚动条区域大小计算;但是不同浏览器或者移动端下,因为屏幕大小不同,中间滚动区域也会不相同,我们可以使用定位进行滚动区域大小的设置;

上拉加载更多的实现:Scroll内置上拉加载更多监听事件scroll.on('pullingUp',()={}),需要设置pullUpLoad属性,用户可以自定义传入属性值以实现上拉加载更多事件的监听是否;Scroll组件将内置的上拉加载更多监听事件传递出去,在首页组件下进行调用,并通过调用网络请求当前页面下的数据;这里需要注意,当我们完成上拉加载更多时,必须要进行scroll.finishPullUp的调用,才能进行下一次的上拉加载更多;

滚动条区域的Bug:Better-Scroll在决定有多少区域可以滚动时,是根据scrollerHeight属性决定的;scrollerHeight属性是根据Better-Scroll的content中的子组件高度决定的;因为页面中的图片数据是异步加载的,然后在better-scroll计算可滚动长度时,计算值可能为未加载图片的高度;因此在进行上拉过程中出现卡顿设置无法上拉;

解决方法:首先监听图片加载完成后,通过scroll.refresh()进行重新刷新计算滚动高度大小;如何监听图片加载完成:在原生JS中使用img.onload = function(){}图片 加载完成就执行回调函数,Vue中封装了图片加载监听事件,只需要在图片标签中添加@load = '监听方法'

这里涉及到如何在商品子组件拿到Scroll对象?

首先明确两者的关系,GoodsListItem是GoodsList的子组件,GoodsList又是Home的子组件,而Scroll也是Home的子组件,因此GoodsListItem不能直接从Scroll中获取scroll对象及其方法;解决方式有三种,一种是将GoodsListItem中的图片加载完成事件传递给GoodsList,然后GoodsList在将该事件传递给Home,在Home下监听并获取scroll对象以完成刷新;太麻烦!

另一种是通过Vuex对象完成数据状态管理,GoodsListItem中可以直接拿到this.$store改变Vuex中某个属性的数据状态,在Home中引用该Vuex中的属性,并且实时监听Vuex中属性的改变,一旦数据状态发生变化就可以实现scroll.refresh

还有一种是事件总线,管理事件,不同于Vuex状态管理,在GoodsListItem中通过this.$bus.$emit('test')向事件总线发送一个事件,然后在Home中进行监听事件,this.$bus.$on('test',function(){});默认情况下$bus的对象是没有内容的,因此需要在main.js通过向Vue的原型对象添加相关方法和属性,因此将Vue实例赋值$bus,这样就可以实现Vue相关方法:Vue.prototype.$bus = new Vue()

注意!!这里涉及到生命周期函数,组件对象是否加载完成的问题,我们在created生命周期函数中加载使用scroll对象及其相关方法,有时候可能会出错,因为在mounted中组件对象可能还未挂载,所以我们访问的对象是null,因此我们在封装Scroll相关方法时,通常做一个判断:this.scroll && this.scroll.scrollTo $$ this.scroll.scrollTo(x,y,time);另外我们的监听函数需要在mounted生命周期函数中;

—总结:因为涉及到非父子组件通信,所以我们选择了事件总线,通过$bus创建一个事件总线,这里需要将$bus添加到Vue原型对象上Vue.prototype.$bus = new Vue();然后可以通过this.$bus.$emit('事件名称',参数)将事件传递到事件总线;并通过this.$bus.$on('事件名称',回调函数(参数))实现监听事件;

优化—刷新频繁的防抖动函数

—例如在搜索框进行搜索的时候,会监听搜索栏中的信息,当搜索栏的内容发生变化,就会向服务器发送请求,但是频繁请求会对服务器压力很大;因此需要频繁刷新的防抖动操作!可以将防抖动创建一个组件,便于复用

这里是对refresh非常频繁的刷新问题进行防抖debounce/节流throttle操作!

—防抖函数起作用的流程:

【1】如果直接执行refresh函数,那么他会执行多次(图片有多少,执行多少次);

【2】可以将refresh函数传入到debounce函数中,生成一个新的函数,并且设置定时器函数,进行等待,在等待时间内,完成下一次刷新,这里设置取消上一次刷新操作以实现避免多次刷新,起到防抖作用;

函数实现

debounce(func,delay){
 let timer = null
//返回一个新的函数 
 return function(...args){
    //取消上一次执行的timer 
     if(timer) clearTimeout(timer)
     timer = setTimeout(() => {
         //延时一段时间执行刷新函数,并且在延时过程中已经取消之前的刷新操作,所以不会频繁的进行刷新
         func.apply(this,args)
     },delay)
 }
}

浏览器事件循环机制

—生命周期函数:created()mounted(),前者是创建组件后就调用,这时只是完成数据的初始化,可以进行网络请求,无法访问页面的DOM元素;mounted()中是组件已经完成挂载,可以获取DOM元素,因此我们滚动条一般都是在mounted()中进行创建调用的;这里created()函数和mounted()钩子函数的使用区别:https://blog.csdn.net/ygy211715/article/details/80079603

  1. 返回顶部组件的封装

—项目需求:点击按钮,直接返回顶部位置;

项目实现

监听点击事件:该需求下对点击事件进行监听,可以通过两种方式实现:

(1)可以直接在当前组件下监听点击事件,然后传递给父组件,父组件在我们上面封装的Scroll滚动条组件中完成事件响应函数(通过scrollTo()滚动返回顶部);较麻烦;

(2)直接在首页中监听组件,注意:原生元素可以直接进行监听事件,但是组件监听需要添加native修饰符才能进行监听;

返回顶部事件响应:当前在首页下可以直接通过this.$refs.scroll拿到Scroll组件对象,这样我们就可以获取滚动条对象的属性和方法;这里需要用到scrollTo函数实现返回顶部操作,内传三个参数,x,y和返回时间大小;

实现返回顶部的隐藏:在首页中默认不显示,只有滚动到一定位置下才会显示返回顶部,因此需要监听滚动事件,当滚动到特定位置显示返回顶部,这里需要将Scroll子组件的监听滚动事件传递出去以供父组件进行监听调用;并通过v-show判断是否显示返回顶部;

  1. 首页离开缓存状态

    —项目需求:当用户离开首页去其他页面时,保存记录当前首页的状态和位置,便于用户返回首页时,还在原来的位置和状态;

    项目实现

    —默认情况下,当进行页面跳转时候,路由会自动将其状态进行自动销毁,进入destroyed生命周期函数,当返回首页又会自动创建组件;如果不想将其状态销毁,可以在路由外包装一下keep-alive记录离开状态,不会随意进入销毁函数;

    —但是由于应用了Better-Scroll,有时候keep-alive不起效果,我们可以在离开首页时保存一个位置信息,而返回首页时,将位置信息设置为原来保存的位置信息;

    —这里就用到了我们的activateddeactivated生命周期函数,分别在deactivated离开时记录当前首页位置,在activated进入时设置离开前的位置,并需要首先进行一次刷新this.$refs.scroll.refresh()

标签:Vue,封装,可以,学习,开源,切换,组件,监听,首页
来源: https://blog.csdn.net/ImmortalSYM/article/details/123055854

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有