vue4

axios比ajax更先进:

服务器地址:http://123.207.32.32:8000/home/multidata

安装:

 

 通过url给服务器发送网络请求,用then处理服务器返回的东西:

 

 

 

 

 

 如果不写method,就默认是get请求方式,如果要改为post:

 

 

 get传参可以直接写到url里面,也能单独写一个params对象:

 

 

 如果要发送2个网络请求,等这2个请求都完成后再处理服务器返回结果:

 

 

 如果不想以数组作为参数接收,而是把服务器数据分别传给res1,res2:

 

全局配置,利用defaults配置好之后,每一个请求的url前面都会加上http://,每一个请求的超时都被设置为5s

 

 

 

 

 

 

 

如果不同请求用自己默认的设置,而不考虑全局的,则创建请求对应的示例,第一段代码表示设置这个实例的默认:

 

 

如果另外一个请求地址默认是别的地址,则再创建一个实例:

 

 

把第三方的插件封装到1个文件中,然后让其他组件引用这个文件,这样当这个插件要换掉时,只用改1个页面即可:

scr新建文件夹network,network下新建request.js文件,第一个参数是用户请求的参数,第二个参数是用户传来一个函数,用于处理请求成功该做什么:

 

 

 

 

 如果main.js要用这个插件:

 

 

 第二种封装方法:

instance()就会返回promise对象,不用再封装为promise了

 

 

 

拦截器:

在这个实例发送请求时,把请求拦截下来可以做些事情,例如log,然后再return走,继续发送请求,如果没有return,请求就发不过去了:

 

 相应拦截:

在请求回来时,拦截:

 

大项目:

建立GitHub仓库:

 

 

 

 

把新仓库拿到vscode中:

 

 

 

 

 

把项目create的文件拷贝到clone下来的项目中:

 

 

 解决红色问题,更新远程仓库:

 

 

 

 

 

 

 

 

查看:

 

 

 或者把本地的仓库直接链接到远程仓库

 

 

 

 项目首先要划分目录结构:

注意:assets用于存放资源,其下再新建css和img文件夹,common文件夹用于存储具有公共变量和函数的js文件,components文件夹下新建common文件夹和content文件夹,common用于存放完全公共的组件,外面的项目也能用,而content仅存本项目公共的组件

 

 

 把素材的normalize.css拷贝到到css文件夹下,为了标准化标签。再把base.css拿过来。

css中:root是获取根元素,此处为html标签,css中通过--来定义变量,后面再通过var()来使用变量

 

 

配置别名:

在项目下新建js文件:

 

 

 

 

 

 为了统一编程风格,比如缩进几个字符,此时把cli2的editorconfig拷贝到项目下:

 

 导航栏

 

 

 说明:

拷贝tabbar:

 把之前的tabBar文件夹拷贝到components的common文件夹下,把mainTabBar文件夹拷贝到content文件夹,因为它仅和项目相关。再把其余的东西拷贝过来,注意此处要.css的后缀不能省略!

把网页图标换了,位于public目录下

定义导航栏组件到components的common文件夹下的navBar文件夹下,设置3个插槽。在home组件里面使用起来。

注意:导航栏在不同的组件中的字体颜色不同,则在哪使用它就在哪个组件中给它设置颜色,如在home中设置字体颜色,和导航栏背景颜色

home组件对外发送请求,获得请求后分发给它的小组件们。由于home组件可能会发送很多请求,所以在network下面再建立一个home.js文件专门用于发送请求。接着在home组件里面通过create函数把请求到的数据拿过来,并分开保存到不同变量中。

 

轮播图:

 

说明:

<style scoped>:该vue内部的css样式仅仅对本vue有用,是私有的。

在组件标签写:aa="asd",可以把asd变量传递给该组件定义的aa变量

轮播图从素材的components/common文件夹下的Swiper拷贝过来,由于使用这个轮播图组件的代码有点多,就在views/home下再建立文件夹childCom,childCom专门用于存放Home里面的私有小组件,然后建立一个HomeSwiper组件,通过引用Swiper里面的index.js导入组件,然后使用轮播图组件,然后再把该组件注册到home组件中。网络请求是外面的home组件发的,然后传到HomeSwiper中。注意:如果子组件props的变量是对象或数组,则默认值必须是函数。

 

推荐:

 

 

 说明:

推荐模块recommendView,做法类似上面,其中,在childCom再建立RecommendView组件

特色:

 

 

说明:

 做法类似上面,这个其实是个img,这个img是放在了a里面

导航栏在上下滚动时是不会消失的,所以position:fixed,但这个样式是写到使用导航栏的home组件里的。

ul>li{列表$}*100:可以列出列表1,列表2....列表100

tabControl:

类似上面建立tabControl组件,由于本项目会多次用到,此处把它放到components/content文件夹下。由于这个组件内部都是分为n栏,只是文字不同,那么就不用slot了,而是让文字从外面传进去,在组件里面用v-for显示出来。为了点击哪个哪个就为红色,则一开始就赋值每项一个index属性,再设置一个公共的currentIndex属性,利用currentIndex==index以及点击事件来实现一个是true,其他为false的现象。由于向下滚动到一个时候,这个组件就开始悬浮起来,此时设置position:sticky,top:44px就能实现。

商品列表:

 

此时请求三类数据,在home。vue建立变量:goods:{

'pop':{page:0,list:[]},

"sell":{page:0,list:[]},

"sell'':{page:0,list:[]} 

其中每个属性代表一类数据,请求到的数据存到对应的list里面,而page表示当前该请求该类型的第几页数据。

home.js里面新增函数getHomeGoods(type,page)进行请求数据,在home.vue里面进行赋值,此时created函数内代码太多了,新建methods方法转移代码的主要部分。当某一页的数据请求到后,对应的page要+1

要展示数据需要2个组件:GoodsList和GoodsItem,在components/content下建立goods文件夹,再建立这2个组件。外面的home组件把数据传给GoodsList,然后GoodsList利用GoodsItem和v-for显示出来数据,同时再传数据给GoodsItem,在GoodsItem里面把图片,标题,价格,搜藏显示出来。

 

为了实现点击tabControl可以切换数据,可以利用子传父的emit把currentIndex传到home那里。

滚动:

iscroll和better-scroll是库,可以从上面用一下滚动的库。

 

 

 

 

使用:better-scroll引入后,要在mounted(){

new BSroll(document.querySelector(‘content’))

mounted是在加载完dom元素后调用的,而created是在加载之前调用的

其中内容要长这样,外面有个元素包着它

且这个元素设置高度!!!!且当加载到最后一张图片时要调用它的refresh!!!

这个元素里面只有1个子元素,此处这个元素指的是div:

<div class="content">

<ul>

<li>内容

.....

关于事件监听的使用:

probeType:要不要监听滚动

click:BScroll里面的若有类似按钮的点击事件,则这个点击事件要不要生效

pullUpload:要不要触发上拉加载更多事件

finishPullUp():如果不写的话,只能触发一次上加载更多事件

 

 

 

在A.vue里面,给组件或者标签里面添加ref="aa",可以在A.vue方法体里面通过this.$refs.aa获得这个组件或者标签 

css中:height:100vh,表示100%的viewport height

height:calc(100% - 93px)表示父元素内容区的高度-98px,注意如果这个元素设置了绝对定位,则这个就没用了,但是可能出现bug,因为加载问题,子元素可能拿不到父元素的高度,100%就没意义了

把第三方插件better-scroll封装起来到component/common文件下的bScroll文件的BSrcoll.vue里面,该组件放置一个slot,home组件引用它时,把home里面的内容都夹在这个组件标签中。

为了设置根元素的height,还可以通过子绝父相让子元素相对于父元素定位的方法,只设置top和bottom,那么中间的空间就能全占了,以此把content定位到合适位置。但是注意此时的子元素的top和bottom是相对于父元素的,所以class=home的父元素也得设置高度,否则子元素也没有高度。

如果给组件添加类名,则类名最终写到了组件定义的template的根div上

小箭头:

 

回到顶部:

 外面的组件通过$refs拿到子组件后可以直接.来调用内部的方法

给组件写监听事件时,要加上.native,比如@click.native,@click表示组件内emit一个"click"事件

滚动组件.scrollTo(0,0,500),可以使得滚动组件(new BScroll出来的)回到顶部(0,0),花费500ms

把这个小组件写到components/content/里面,再装入图片并定位右下角,在定义一个回到顶部事件供home组件调用。

对于props,如果外面的组件标签里面是name=''123',则传给子组件的是字符串123,如果是:name="123",则能看出类型来,传给子组件的是数字123

显示与隐藏:

滚动到某一个地方时才显示出来:

组件内部封装一个方法用于监听滚动,并把postion返回到外面的组件,同时BScroll组件用props接受一个布尔变量,看看父组件要不要监听滚动。父组件利用v-show来显示或者隐藏。

总结参数:

事件触发时,标签内部(如果是组件内部要加.native,否则是接收组件内部emit出来的事件):

传递普通参数:@click="go(123)" ,定义:go(t){}

获得事件对象:@click="go",定义go(e){}

子组件this.$emit("go",t),父组件:@go=“fun”,定义fun(t){}

bug:

A组件向B组件发送事件(通信):在main.js中,Vue.prototype.$bus=new Vue()注册一个$bus, 然后A组件中方法中的this.$bus.$emit('aaa'),在B组件就能监听到:this.$bus.$on('aaa',()=>{}),以此实现A和B组件的通信

 

 

 

 图片加载完成会触发load事件。

防抖动:

由于每个图片加载一下都会进行refresh,性能低下,此时需要当第一个图片加载完毕时,它需要等一段时间再refresh,当下一个图片加载完了,它先查看之有没有即将要执行的定时器操作,如果有的话就取消掉之前的refresh,接着自己再等一段时间再refresh。。。。这样到最后也就只有几张图片refresh了。下图的func.apply就是调用函数,...arg表示如果有参数传进来,就存下来,下图中不断调用的refresh()是return的函数,但是用到的timer只初始化了一次。这种结构可以实现初始化一次变量,但后面多次调用函数时,可以共用这一个变量。

 

我的方法:

 

 可以把debounce再做一次抽取,放到common文件夹下的util,js里面,然后外面的home.vue导入使用它

上拉加载更多:

类似上面,里面的scroll会触发滚动事件,但是把这个滚动事件$emit外面的home来处理。在home里面,再进行axios请求即可,此时list就会多出来东西,这是home显示的东西就更多了。注意为了多次上拉加载更多,需要finishPullUp(),可以再把它封装一下。

bug:

点击tabControl失效了,此时在scroll组件里面,写入click:true

当出现错误提示:Cannot read property 'finishPullUp' of undefined,说明是有了null.finishPullUp,此时用&&解决

tabControl吸顶效果:

利用:组件.$el可以获得组件内部定义的根标签,offsetTop可以获得标签到顶部的距离,但是tabControl需要等待前面的图片加载完毕后获取的offsetTop才是有效的。现在假定只要轮播图图片加载就行,由于有多张图片,此时利用一个布尔变量使得只要有1张图片传过事件来,其他图片就别传了。

可以在home里面再复制一个tabControl,放到NavBar下面,同时监听滚动,利用一个布尔变量,当滚动到某个位置时显示出这个tabControl,父组件要给子组件传递值,可以props,也可this.$refs.子组件.data

离开首页时记录离开的状态:

先keep-alive给router-view让它活着,滚动会出现问题。此时在home组件中利用deactivated记录离开时的scroll.y值到一个变量中,在activated函数中再滚动到这个y值即可。

跳转到详情页:

在goodsItem里面监听点击,然后路由跳转并把图片id传过去,配置路由,再在views下新建detail文件夹,再新建Detail组件,在组件中通过激活的路由显示出来。

详情页的导航栏:

 

 

 由于导航栏代码稍微多点,在detail文件夹下新建childCom,再新建navDetail组件用于写导航栏,然后设置好样式和点击事件

 

轮播图:

 

 向服务器发送请求时,再封装一个detail.js,外面把id传入js里面,js通过request发送请求给服务器。然后插入轮播图组件。为了使得一点进来就能创建一个新detail组件,则在keep-alive那里exclude

 

 

 展示信息,通过建立在detail.js里面封装一个类,目的是让这个类定义属性来分类接受服务器传来的数据,然后在detail.vue里面对请求到的数据存储到类所定义的对象里面,然后再创建一个显示内容的组件,把这个对象传给这个组件并让它显示出来。

 

店铺信息展示,操作同上

 

加入滚动效果:利用用scroll把nav下面的包起来就有滚动效果了。同时为了达到悬浮效果,设置nav为相对定位以及它的z-index

 

新建vue来用来展示商品图片,每张图片load结束后,向detail组件emit事件来让scroll刷新一下高度,具体的刷新延迟优化在common/utils.js里面实现。

 

 

参数主题,封装起来

 

 

评论主题封装起来

 

 

推荐主题封装起来 

 

注意: 组件标签里面 :abC =..,可能不区分大小写,最后传给了组件里面的abc

 this.$nextTick(()=>{

  

})该函数当组件渲染完毕后(不包括组件内的图片渲染完毕),执行

 

实现点击详情页的主题滚动到对应的地方:先获取点击的index值(子组件emit),detail.vue在图片加载完毕之后获取各个模块的offsetTop并存到一个数组中,当点击某个主题就scrollTo那里。还要对获取offsetTop操作实现防抖。

 

效果: 滚动到某个主题时,选中对应的标题:

bscroll监听滚动并emit外面,外面detail利用4个offsetTop所在的数组进行判断,然后操纵tab里面的currentindex

 

 

封装起来底部的工具栏

 

 回到顶部: 利用混入实现home和detail里面都可以,但是注意混入的周期函数最后与主vue叠加,但是methods是覆盖关系

 

添加到购物车:detail接收bottomBar发来的点击事件,随后将部分商品信息集成到一个对象中,然后利用vuex管理,此时要安装vuex --save。vuex利用一个数组来存储各类商品,每类商品中有属性count表示该类有多少个商品被添加进去了。然后在cart.vue的navbar中展示出总的个数,其中vuex采用如下目录结构:

在购物车界面通过mapGetters来调用getters中的函数

 

 

 

将商品列表封装成list组件,然后在list组件中展示更小的item组件,每个对象数据传到item里面,按钮也封装起来。给大的list组件套一个scroll组件便于滚动。

由于有未选中和被选中2种状态,则给每一个添加进购物车的对象一个选中的属性。

当点击时再切换为未选中,同时该布尔值值传给组件内部让它展示按钮的选中和未选中的样式。

再对底部工具栏封装一个组件,该组件有3个div,分别显示3块,按钮采用之前封装过得那个按钮。采用flex来布局。合计价格采用计算属性来计算出来(利用filter和reduce)。

全选效果:如果所有item都选中,则选中,反之:外面组件利用计算属性,根据数组是否有未选中的来得到一个布尔值,然后传到组件里面让它做对应的显示

当点击全选时,若之前为是不全选,则数组中所有对象的属性置为true,若之前已经全选了,则所有置为false

 注意本质是在改变对象中的checked属性,外界都围着它转。

 

购物车弹窗:利用actions.js返回promise对象,当第一次添加进商品时,显示添加成功;当第二次添加时显示商品数量+1。可以利用mapAction往vue里面的methods自动注入方法。

注意:vue.use(toast)会调用toast的install函数

 

 

 采用插件封装的形式封装Toast弹窗,然后外面直接调动即可:

 

 

fastclick解决移动端300ms延迟:

 

 

 

 

图片懒加载:

 

 

 

 

 

 

 

 

 把img的src改了:

 

 

 

 

 占位图效果:

 

 

 代码的10px是css的像素,不是设备的。(pc端等于设备像素)

屏幕尺寸:对角线长度,用于衡量屏幕大小

屏幕分辨率:屏幕像素点的个数,高清屏分辨率大

位图像素:图像的像素

下图是的320*568是设备独立像素

 

 

 

像素密度:

 

 

 

 将px单位转化成vw单位:

 

 exclude是忽略某些文件,要使用正则表达式:

 

 

windows下部署:

 

 

 

下载Nginx

 

 

 运行exe:

 

 

拷贝dist文件夹过去,然后把dist里面的东西复制到外面:

 

 

 

 

或者修改配置:

 

 

 

改:

 重启nginx:cmd输入 :nginx -s start

远程Linux下部署:

通过ssh登录到远程服务器

yum install nginx

修改配置:

 

 把dist文件夹拷贝过去

 

访问:

 

 可以借用软件:

 

 vue的响应式原理:

 

假定此处的obj代表vue中的data,然后遍历里面的属性:先拿到原来的值,然后在defineProperty里面set中监听属性值的改变,若外面vue改变了属性(例如message),

则通知(发布者订阅者模式)所有用到message的地方进行更改;get中只要外界要获取message,则都要调用get方法,get返回原值。 

发布者订阅者模式:只要用了message的都是订阅者,把它们放到发布者对象中的一个数组里面,当message要更改时,则遍历订阅者数组让每个订阅者更新一下

 

 图解:

new Vue之后,对data中的每个属性创建对应的开发者,每个开发者有自己的一堆订阅者(每compile一个{{name}}则创建一个订阅者(watcher),然后把它添加到开发者的订阅者数组中),

当某个属性发生了变化,则对应开发者调用notify遍历自己的订阅者,让它们都update。

 

 

 

 

 

 

posted @ 2020-02-05 20:21  Jary霸  阅读(843)  评论(0编辑  收藏  举报