网站模块删除,如何在手机上开发软件,wordpress 添加图片不显示,什么是wap网站兄弟组件之间的联动所谓的兄弟组件之间的联动#xff0c;其实就是实现点击右侧的字母就能跳转至对应的首字母城市#xff0c;因此列表组件需要知道右侧的字母列表的点击事件所对应的元素字母#xff0c;这就需要兄弟组件间的数据传递了(Alphabet组件与List组件之间的通信)其实就是实现点击右侧的字母就能跳转至对应的首字母城市因此列表组件需要知道右侧的字母列表的点击事件所对应的元素字母这就需要兄弟组件间的数据传递了(Alphabet组件与List组件之间的通信)可以使用到中央数据总线Bus但是由于这里的业务逻辑不是很复杂因此可以将Alphabet组件内的信息传递到City组件(子组件向父组件传递信息发布订阅模式)然后City组件向List组件传递信息(父组件向子组件传递信息属性传值方式)。在gitee的分支栏点击新建分支city-components然后记得将本地master分支切换到city-components分支。字母点击跳转打开Alphabet.vue文件给字母表中的字母添加一个click事件然后尝试将点击的字母在控制台上进行输出显示 {{key}} 然后在script标签添加这个handleLetterClick方法methods: { handleLetterClick (e) { console.log(e.target.innerText) } }可以测试一下当你点击右侧列表中的字母控制台是否真的输出了对应的字母前面说了由于这里的业务逻辑不是很复杂因此可以将Alphabet组件内的信息传递到City组件(子组件向父组件传递信息发布订阅模式)然后City组件向List组件传递信息(父组件向子组件传递信息属性传值方式)。那就开始编写使用发布订阅模式实现Alphabet组件内的信息传递到City组件的代码。修改子组件Alphabet.vue中handleLetterClick函数代码为methods: { handleLetterClick (e) { /** 注意此处必须使用innerText而不是innerHTML **/ this.$emit(change, e.target.innerText) } }接着去父组件City.vue中监听该chang事件请定义相应的handleLetterChange去接收子组件传递过来的信息handleLetterChange (letter) { console.log(letter) }控制台测试发现当你点击右侧列表中的字母控制台仍然输出了对应的字母。接下来就是父组件City.vue通过属性传值的方式将数据传递给子组件List.vue。修改父组件City.vue中handleLetterChange函数代码为 handleLetterChange (letter) { this.letter letter }然后在父组件中的data中返回letter并将其通过属性传值给city-list组件 ... ... data () { return { ... letter: }然后在子组件List.vue中通过props来接收数据 props: { cities: Object, hotCities: Array, letter: String },当List.vue发现letter有变化的时候就显示跟letter首字母相同的城市列表这种功能可以通过侦听器来实现watch: { letter () { console.log(this.letter) } }控制台测试发现当你点击右侧列表中的字母控制台仍然输出了对应的字母。还记得之前推荐的那篇关于better-scroll的文章当 better-scroll 遇见 Vue么里面介绍了如何滚动至某个元素。既然是滚动至某个元素那么肯定需要选择某个DOM节点了Vue提供了ref来选择节点(List.vue)然后使用侦听器来监听letter的变化 watch: { letter () { if (this.letter) { console.log(this.$refs[this.letter]) } } }当你点击某个字母时控制台输出而这个索引为0的div.area区域中包含了我们所需要的的城市列表信息既然这样就可以直接获取到对应的DOM节点并将该节点传递给better-scroll里面有一个scrollToElement方法之后就能实现点击某个字母城市列表页就会显示对应的城市信息 watch: { letter () { if (this.letter) { const element this.$refs[this.letter][0] this.scroll.scrollToElement(element) } } }拇指滑动跳转前面介绍的是点击右侧的字母就能跳转至对应的首字母城市其实比这个更普通的 就是当你拇指按住字母表上下滑动时左边List组件也会相应的上下跳动。实现这个需要首先我们要监听使用者的手指记录时候开始点击字母列表(touchstart)什么时候开始滚动(touchmove)以及什么时候离开字母列表(touchend)等等自然而然地想到使用事件监听。注意我们还需要定义一个标志状态(touchStatus)默认为flase只有当你手指触摸的时候才会变成true其实就是指定这三个函数的执行顺序 {{key}} 现在我们需要知道当你拇指在滑动的时候你的拇指停留在哪个字母上这件事情其实是较为复杂的可以提供一种思路仅供参考先获取A字母距离顶部的高度然后当你滑动的时候获取你当前字母距离顶部的高度接着将后者减去前者得到一个差值最后用这个差值除于每个字母的长度就能得到这是第几个字母。然后让该字母触发对应的事件即可那么这样你需要新建一个数组用于存放字母然后根据索引来获取字母可以使用计算属性 computed: { letters () { const letters [] for (let i in this.cities) { letters.push(i) } return letters } },上面的计算属性其实就是得到一个类似于[A,B,C,D]的数组。然后你城市字母表遍历的对象就不再是cities而是letters了(那就不需要使用key了直接遍历输出item就可以) {{item}} 接下来继续编写handleTouchMove函数的内容这个函数就是用于计算当你拇指在滑动的时候你的拇指停留在哪个字母上。实现的逻辑是先获取A字母距离顶部的高度然后当你滑动的时候获取你当前字母距离顶部的高度接着将后者减去前者得到一个差值最后用这个差值除于每个字母的长度就能得到这是第几个字母。第一步在template中给DOM节点添加ref属性用于获取某个DOM节点:refitem第二步修改handleTouchMove函数为 handleTouchMove () { if (this.touchStatus) { const startY this.$refs[A][0].offsetTop console.log(startY) } },通过测试发现当你拇指在滑动的时候控制台始终输出61这个61就是A字母距离页面顶部(注意是蓝色区域底部)的高度然后就可以获取每个字母距离整个页面的高度里面有一个最小的值就是拇指距离整个页面最小的高度如果你想要获取某个字母距离蓝色区域底部的高度可以将其高度减去蓝色区域底部的高度79(43(Header组件高度)36(Search组件告高度)79)然后除以20(每个字母高度)并向下取整就能得到每个字母的索引 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) console.log(index) } },测试发现拇指移动到字母M处右侧显示正常最后使用子组件Alphabet使用发布订阅模式向City组件传递数据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]) } } },测试发现功能显示正常。城市列表页新能优化接下来就是对上面的代码进行优化因为startY是一个定值而按照目前写的代码则是每次都需要去执行这会造成性能低下。可以在data中return一个startY(初始值为0)然后定义一个生命周期函数update只有页面的数据被更新同时页面完成了渲染时该方法才会被执行 data () { return { touchStatus: false, startY: 0 } }, updated () { this.startY this.$refs[A][0].offsetTop },handleTouchMove (e) { if (this.touchStatus) { 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]) } } },我们知道页面一开始的时候cities变量是空值也就是Alphabet组件内不会显示任何信息然后通过ajax获取到数据时Alphabet组才会被重新渲染之后会触发生命周期函数updated这时候开始计算蓝色区域底部与字母A标签的距离。还有一个优化就是函数节流。函数节流就是限制一个函数在一定时间内只能执行一次这里就是当你拇指在字母表中上下移动时touchmove函数执行的频率非常高会造成性能低下因此可以借助于函数节流来优化该代码。具体的函数节流介绍可以参看这篇文章JS进阶篇1---函数节流(throttle)此处采用计时器规定在一定时间内函数才允许执行。打开Alphabet.vue文件先return一个timer对象初始值是null其次修改handleTouchMove函数代码为handleTouchMove (e) { if (this.touchStatus) { if (this.timer) { clearTimeout(this.timer) } this.timer setInterval(() { 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) } },原理非常简单先判断timer计时器对象是否存在存在就清空该计时器避免缓存否则就定义一个计时器并设置计时器时间为16毫秒即每16毫秒才计算一次这样可避免不必要的计算工作。搜索功能实现在gitee的分支栏点击新建分支city-search-logic然后记得将本地master分支切换到city-search-logic分支接下来开始进行搜索框的业务逻辑开发。打开city文件夹中的Search.vue组件修改其中的template代码为 123 这里面其实就是新增了一个搜索结果展示的区域也就是.search-content类所占区域接着在style标签中新增.search-content类所对应的样式(注意它应该和.search类是平级关系).search-content z-index: 1 overflow: hidden position: absolute top: 1.58rem left: 0 right: 0 bottom: 0 background: green然后需要实现搜索信息与结果展示区域的联动就需要使用到数据的双向绑定 最后结果肯定是显示城市那么需要从父组件City中接收cities修改City.vue组件中的template代码为 .... 然后在子组件Search.vue中通过props来接收cities props: { cities: Object },然后我们在子组件Search.vue中return一个数组list(该数组用于存储搜索结果)和计时器timer(函数节流使用) data () { return { keyword: , list: [], timer: null } }接着我们定义一个侦听器用于监听keyword的变化 watch: { keyword () { if (this.timer) { clearTimeout(this.timer) } this.timer setInterval(() { // 书写在cities对象中查找某个元素的逻辑 const result [] for (let i in this.cities) { // i就是字母A,B...而this.city[i]就是数组value就是数组中的每一项 this.cities[i].forEach((value) { if (value.spell.indexOf(this.keyword) -1 || value.name.indexOf(this.keyword) -1 ) { result.push(value) } }) } this.list result }, 100) } }在city.json文件中我们定义的cities结构为cities: { A: [{ id: 56, spell: aba, name: 阿坝 }, { id: 57, spell: akesu, name: 阿克苏 }...也就是cities本身是一个对象里面又包含了一个数组作为值而数组中包含的则是一个个对象。注意if语句中的判断条件为value.spell.indexOf(this.keyword) -1 ||value.name.indexOf(this.keyword) -1也就是通过拼音或中文都可以查找是否能找到匹配的数据。接下来就是对搜索结果的布局进行优化给搜索结果添加一个.search-item类和一个边框类.border-bottom {{ item.name }} 然后给.search-item类添加样式并修改.search-content类的背景颜色为#eee.search-content z-index: 1 overflow: hidden position: absolute top: 1.58rem left: 0 right: 0 bottom: 0 background: #eee .search-item line-height: .62rem padding-left: .2rem background: #fff color: #666测试发现页面显示正常但是搜索结果是无法滚动的此时可以借助于bertter-scroll来实现。第一步获取到search-content类节点DOM {{ item.name }} 第二步导入Bscroll类及创建该对象只需这两步就完成了页面滚动的效果。还有一个问题就是当你输入完并清空搜索框的时候搜索结果依旧还是存在其实只需要当你的keyword为空的时候你将这个list设置为[]即可在侦听器中添加实现上述功能的逻辑 watch: { keyword () { if (this.timer) { clearTimeout(this.timer) } if (!this.keyword) { this.list [] return } ... }这样就解决了这个问题。新的问题又来了就是当你输入一串非常长的字母或者说是输入的关键词不能匹配任何城市时前面我们是什么也不显示其实这个是有一点问题的我们最好是在页面上添加诸如“找不到对应的城市”等信息。最简单的方式就是使用v-show来进行显示 {{ item.name }} 没有找到匹配的城市 这样我们就实现了当list的长度为0的时候才显示“没有找到匹配的城市”字眼但是这样会造成一个问题就是刚开始你不输入关键词的时候也会出现这个“没有找到匹配的城市”字眼把热门城市和城市列表给遮住了。这个问题还是可以通过v-show来解决(只不过这次将v-show 标签加到search-content类上) {{ item.name }} 没有找到匹配的城市 这样就完美地解决了上述问题。前面介绍过html中最好不需要包含计算逻辑(在“没有找到匹配的城市”标签上使用了取反运算)没有找到匹配的城市因此需要将这个取反的逻辑使用计算属性来代替 computed: { hasNoData () { return !this.list.length } },自然而然就需要修改上面的template中的取反运算代码为没有找到匹配的城市这样就完成了搜索框的业务逻辑。最后就是将我们的代码上传到city-search-logic分支并且将其与master分支进行合并相应的步骤如下git statusgit add .git commit -m search logic finishgit pushgit checkout mastergit merge city-search-logicgit push