标签:bullet 上海 proxy 打开 tail 修改 注入 点击图片 targe
前面一些css和html布局就不多说,就说几个关键点。
@import ‘~@/assets/styles/variables.styl‘
引入这个文件,然后就能使用 $bgColor代替了;‘@‘: resolve(‘src‘)
,所以我们也可以在底下加上,‘styles‘: resolve(‘src/assets/styles‘)
,实现一样的功能。Vue.use(VueAwesomeSwiper)
,然后在home.vue中也引入并且注册局部组件,最后在components目录下新建swiper.vue组件文件(和之前header过程一样,以后每次加入子组件都这样).wrapper
overflow: hidden
width: 100%
height: 0
padding-bottom: 36.64%
下面的那里是宽高比,设置成这样不会有浏览器兼容的问题,最常使用。
加上下面的小圆点,插件里面也实现好了,只需做修改即可(查看官方文档哈);
不过这里要注意的是,swiper.vue中的style设置了scope属性,也就是在这个文件中修改的样式不会影响到其他文件的样式,所以这里要用到穿透技术:
.wrapper >>> .swiper-pagination-bullet-active
background: #fff !important
当然这里可以使用v-for来循环展示图片,就不用在template里写那么多东西了,循环的话就在swiperOptions里加上loop为true即可(查看官方文档即可知);
这里起到的是占位符的作用,这里的padding-bottom和padding-top是相对于父元素宽度的比例。
这里的实现原理和上面swiper几乎一致,就是把上面的swiper相关的标签先粘贴过来,再问题就来了,图标过多同样也要可以左右滑动,所以就要实现分页,那如何实现?
computed: {
pages () {
const pages = []
this.iconList.forEach((item, index) => {
const page = Math.floor(index / 8)
if (!pages[page]) {
pages[page] = []
}
pages[page].push(item)
})
return pages
}
}
//循环的东西变了
<swiper-slide v-for="(page, index) of pages" :key=‘index‘>
<div v-for=‘item of page‘ class="icon" :key=‘item.id‘>
overflow: hidden
white-space: nowrap
text-overflow: ellipsis
//mixins.styl文件中
ellipsis()
overflow: hidden
white-space: nowrap
text-overflow: ellipsis
//在Icon.vue中不要忘记引用
@import ‘~styles/mixins.styl‘
//用的地方直接调用即可
ellipsis()
页面是由一些子组件来构成的,每个子组件都有自己的数据,如果每个子组件都自己发送请求那就要发送很多次导致性能下降,所以干脆就请求一次 把所有数据都获取到。那在哪里请求呢?由代码结构可知,Home.vue中包括了所有的子组件,所以在那里请求是十分合适的。
vue提供了axios来专门用来获取Ajax数据,所以我们使用这个工具,先安装npm install axios --save
,再在Home.vue中引用import axios from ‘axios‘
;
在Home.vue中定义生命周期函数mounted用来发送请求,它调用函数,再往函数里具体添加内容即可:
methods: {
getHomeInfo () {
axios.get(‘/api/index.json‘)
.then(this.getHomeInfoSucc)
},
getHomeInfoSucc () {
}
},
mounted () {
this.getHomeInfo()
}
由于我们的项目还没有上线,要模拟请求就要将数据都存放到本地,这里我们将数据放到static/mock/index.js;
http://localhost:8080/
后加上static/mock/index.json
,页面上就会显示Index.js里的内容;static/mock
;/static/mock/index.json
;但是在项目上线之后,并不再会使用本地模拟的地址,还是得写axios.get(‘/api/index.json‘)
,但直接这么写上线之后是有风险的,所以我们需要一个转发机制,将对以api开头的请求转发到本地文件夹/static/mock下,这时就需要修改配置文件的内容了;
proxyTable: {
‘/api‘: {
//还是请求这个网址不变
target: ‘http://localhost:8080‘,
//只要以api开头 就转发到/static/mock文件夹下
pathRewrite: {
‘^/api‘: ‘/static/mock‘
}
}
},
刚刚已经直到如何获取到Ajax数据了,那现在如何传递到各个子组件?
//父组件
data () {
return {
city: ‘‘,
swiperList: []
}
},
methods: {
getHomeInfo () {
axios.get(‘/api/index.json‘)
.then(this.getHomeInfoSucc)
},
getHomeInfoSucc (res) {
res = res.data
if (res.ret && res.data) {
this.city = res.data.city
this.swiperList = res.data.swiperList
}
}
}
//子组件
props: {
city: String //用来规定数据类型
}
这个问题主要体现在轮播图,由于一开始在父组件里定义的是空数组,所以开始创建的时候还没有元素,等到父组件接收到Ajax传来的数据再送给子组件时,出现的就不是第一页轮播图了;
//swiper标签内加上v-if=‘showSwiper‘
computed: {
showSwiper () {
return this.swiperList.length
}
}
这里要实现点击城市展示城市页面的效果,之前也说过路由就是根据不同的地址显示不同内容的东西,这里通过配置路由来实现页面跳转。
router-link
标签,包裹城市那部分即可;如果你的 exact
设置为false,表示的是 非严格匹配;举个例子:
如果你的请求的路由是: ‘/a/b/c‘;那么他会被匹配到以下路由
/
/a
/a/b
/a/b/c
这里的 第4个路由是你的目标路由, 如果前3个路由的 exact
都是 设置为 false
; 并且路由的顺序是在 4
的前面。那么前面3个的组件都会被渲染,并且默认的,会把 2
当作 1
的子页面,3
当作 2
的子页面,
这样设计的目的,是为了实现路由的嵌套业务。所以你如果不希望这样,要么设置 exact=true
;要么注意顺序。
这种场景在模糊匹配的路由中也是存在的。
所以定义路由的时候,一般都是这样,
/a/b
应该放在 /a
前面/a/b
放在 /a/:id
.list
position: absolute
top: 1.58rem
left: 0
right: 0
bottom: 0
overflow: hidden //关键
然后查看GitHub中better-scroll的官方文档,找到使用方法与说明;
先安装 npm install better-scroll@next -S
引入 import BScroll from ‘@better-scroll/core‘
这里使用的话,参考
watch: {
letter () {
if (this.letter) {
const el = this.$refs[this.letter][0]
this.scroll.scrollToElement(el, 0, 0)
}
}
}
handleTouchMove (e) {
if (this.touchStatus) {
const startY = this.$refs[‘A‘][0].offsetTop //相对头部底部的高度
const touchY = e.touches[0].clientY - 79 //相对屏幕顶部的距离 - 头部的高度
const index = Math.floor((touchY - startY) / 20)
if (index >= 0 && index < this.letters.length) {
this.$emit(‘change‘, this.letters[index])
}
}
}
//在数据项里设置了一个timer定时器
handleTouchMove (e) {
if (this.touchStatus) {
if (this.timer) { //若上次还没执行完 则清除 来执行这一次
clearTimeout(this.timer)
}
this.timer = setTimeout(() => {
const touchY = e.touches[0].clientY - 79
const index = Math.floor((touchY - this.startY) / 20)
if (index >= 0 && index < this.letters.length) {
this.$emit(‘change‘, this.letters[index])
}
}, 16)
}
},
要实现的功能为,在搜索框里输入一部分拼写或汉字,下面可以列出符合的城市名单;
watch: {
keyword () {
if (this.timer) {
clearTimeout(this.timer)
}
this.timer = setTimeout(() => {
const result = []
for (let i in this.cities) {
this.cities[i].forEach((value) => {
if (value.name.indexOf(this.keyword) > -1 || value.spell.indexOf(this.keyword) > -1) {
result.push(value)
}
})
}
this.list = result
}, 100)
}
}
同时这里还要实现以下两个功能:
查找不到相应内容的时候要显示 “没有找到匹配数据”:
v-show=‘hasNotData‘
;搜索框里无内容的时候,搜索页面隐藏(这里好大一个坑,不隐藏虽然什么都不显示,但是后面的内容被遮挡住了,滑动不了!!!花了我八九个小时找原因,各种找better-scroll的原因,错怪了):
v-show=‘hasNotData‘
,这个函数返回!this.list.length
,之所以定义一个函数,是要尽量避免在模板里出现逻辑,将逻辑都放到函数里去实现。Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。
这个状态自管理应用包含以下几个部分:
但是,当我们的应用遇到多个组件共享状态时,单向数据流的简洁性很容易被破坏:
因此,我们为什么不把组件的共享状态抽取出来,以一个全局单例模式管理呢?在这种模式下,我们的组件树构成了一个巨大的“视图”,不管在树的哪个位置,任何组件都能获取状态或者触发行为!
通过定义和隔离状态管理中的各种概念并通过强制规则维持视图和状态间的独立性,我们的代码将会变得更结构化且易维护。
this.$store
访问到;//store实例
export default new Vuex.Store({
state: {
city: ‘上海‘
},
actions: {
//ctx是上下文信息,函数体要通过它来获得commit方法
changeCity (ctx, city) {
ctx.commit(‘changeCity‘, city)
}
},
mutations: {
changeCity (state, city) {
state.city = city
}
}
})
在上面的点击事件处理函数里加上 this.$router.push(‘/‘)
,即可实现,点击切换城市后立即跳转到home页面。
每一个商品点开都有一个自己的详情页,跳转到的页面都不一样,这里通过动态路由的方式,根据商品自己的id来决定跳转到页面的路径。
to=‘路径‘
,而现在改为:to="‘detail/‘ + item.id"
,加了个冒号,动态;tag=‘原本的标签名‘
,这样可以使router-link标签渲染成原本的标签,而不是直接变为a标签,就解决字体颜色变化的问题了。//利用浮动 但是里面的盒子要有固定宽高(比)
display: flex
flex-direction: column
justify-content: center
//将observe应用于Swiper的父元素。当Swiper的父元素变化时,例如window.resize,Swiper更新。
observeParents: true,
//启动动态检查器(OB/观众/观看者),当改变swiper的样式(例如隐藏/显示)或者修改swiper的子元素时,自动初始化swiper。
observer: true
在最顶部的时候,头部header区域是不显示的,当往下滑动时header会随着距离增大而显示出来:
渐隐渐显
const top = document.documentElement.scrollTop
this.opacityStyle.opacity = (top / 140) > 1 ? 1 : (top / 140)
//老师用的mounted和unmounted 但是文档中unmounted并没有,所以用destroyed
mounted () {
window.addEventListener(‘scroll‘, this.handleScroll)
},
destroyed () {
console.log(‘destroyed‘)
window.removeEventListener(‘scroll‘, this.handleScroll)
}
const top = document.documentElement.scrollTop || document.body.scrollTop || window.pageYOffset
//在DetailList组件内
<div class="item-children" v-if=‘item.children‘>
<detail-list :list=‘item.children‘></detail-list>
</div>
<keep-alive exclude=‘Detail‘>
<router-view/>
</keep-alive>
在Router路由里,创建新路由的里面加上以下语句:
scrollBehavior (to, from, savedPosition) {
return {x: 0, y: 0}
}
目前代码调试都是通过浏览器的手机模拟来调试,那真实到手机上打开该页面怎么办?
首先是要修改配置项,先找到本机的ip地址:
但手机或电脑直接访问该地址是无法打开页面的,因为webpack默认不允许用户通过ip地址来访问,所以要修改打包文件,package.json文件,在scripts下的start项后的命令里加上 host 0.0.0.0
,即允许通过ip地址访问;
同一局域网的设备通过输入刚刚查得的ip地址即可访问页面。
npm run build
进行打包,文件夹内会多出一个dist目录;component: Home
//改为
component: () => import(‘@/pages/home/Home‘)
//其余也是这么改
标签:bullet 上海 proxy 打开 tail 修改 注入 点击图片 targe
原文地址:https://www.cnblogs.com/TRY0929/p/13202641.html