兄弟组件通信及滚动逻辑

子组件(字母A/B/C)

Alphabet.vue

<template>
    <ul class="list">
        <!-- <li class="item"
            v-for="(item,key) of cities"
            :key="key"
            @click="handleLetterClick"
            @touchstart="handleTouchStart"
            @touchmove="handleTouchMove"
            @touchend="handleTouchEnd"
        >{{key}}</li> -->
        <li class="item"
            v-for="item of letters"
            :key="item"
            :ref="item"
            @click="handleLetterClick"
            @touchstart="handleTouchStart"
            @touchmove="handleTouchMove"
            @touchend="handleTouchEnd"
        >{{item}}</li>
    </ul>
</template>

<script>
// 引入better-scroll插件
import Bscroll from ‘better-scroll‘
export default{
    name:‘CityAlphabet‘,
    props:{
        cities:Object
    },
    // 计算属性
    computed:{
        // 先定义一个数组。letters=[‘A‘,‘B‘,‘C‘]
        letters(){
            const letters = []
            for(let i in this.cities){
                letters.push(i)
            }
            return letters
            // [‘A‘,‘B‘,‘C‘]
        }
    },
    data(){
        return {
            touchStart:false
        }
    },
    methods:{
        handleLetterClick(e){
            console.log(e.target.innerText);  // 打印点击的字母
            // 子组件传值给父组件。向外触发事件。父组件监听。
            this.$emit(‘change‘,e.target.innerText)
        },
        // 监听左边城市的滚动。
        handleTouchStart (){
            // 手指触摸
            this.touchStart=true
        },
        handleTouchMove (e){
            /*
                1.a到顶部的高度.
                2.当前滑动到哪的位置与顶部的高度。注意:要减去header的高度.
                3.算出两个值之间的差值。除以每个字母的高度。算出当前是第几个字母。
                4.获取到字母,触发自定义事件。传值给父级,父级再传值给兄弟组件。

            */
            const startY = this.$refs[‘A‘][0].offsetTop;  // 1.a到顶部的高度
            // console.log(startY);
            const touchY = e.touches[0].clientY - 79;  // 2.当前滑动到哪的位置与顶部的高度。注意:要减去header的高度.
            // console.log(touchY);

            const index = Math.floor((touchY - startY)/20);  // 3.算出两个值之间的差值。除以每个字母的高度。算出当前是第几个字母。
            // console.log(index);
            if(index >= 0 && index < this.letters.length){
                this.$emit(‘change‘, this.letters[index]);
            }
        },
        handleTouchEnd (){
            // 结束滑动
            this.touchStatus = false;
        }
    }
}

</script>

<style lang="stylus" scoped>
    @import ‘~styles/varibles.styl‘
    .list
        display:flex
        flex-direction:column
        justify-content:center
        position:absolute
        top:1.58rem
        right:0
        bottom:0
        width:.4rem
        .item
            line-height:.4rem
            text-align:center
            color:$bgColor
</style>

父组件

City.vue

<template>
    <div>
        <city-header></city-header>
        <city-search></city-search>
        <city-list
            :hotCities="hotCities"
            :cities="cities"
            :letter="letter"
        >
        </city-list>
        <city-alphabet
            :cities="cities"
            @change="handleLetterChange"
        >
        </city-alphabet>
    </div>
</template>

<script>
// ajax工具
import axios from ‘axios‘

// 引入子组件
import CityHeader from ‘./components/Header‘
import CitySearch from ‘./components/Search‘
import CityList from ‘./components/List‘
import CityAlphabet from ‘./components/Alphabet‘

export default{
    name:‘City‘,
    // 组件
    components:{
        CityHeader,
        CitySearch,
        CityList,
        CityAlphabet
    },
    data(){
        return {
            // 热门城市
            hotCities:[],
            // 城市
            cities:{},
            letter:‘‘
        }
    },
    // 函数
    methods:{
        getCityInfo(){
            axios.get(‘/api/city.json‘)
                .then(this.handleGetCityInfoSucc)
        },
        handleGetCityInfoSucc(res){
            console.log(res);
            res = res.data;
            if (res.ret && res.data){
                const data = res.data
                this.hotCities = data.hotCities
                this.cities = data.cities
            }
        },
        // 父组件监听子组件自定义事件。
        handleLetterChange(letter){
            console.log(‘父组件接收到了letter:‘,letter);  // 父组件接收到子组件接收到的数据。
            // 父组件再通过属性传递给另一个子组件。
            this.letter = letter
        }
    },
    //dom加载完成
    mounted (){
        this.getCityInfo()
    }
}
</script>

<style lang="stylus" scopend>

</style>

兄弟组件(展示城市)

List.vue

<template>
    <div class="list" ref="wrapper">
        <div>
            <div class="area">
                <div class="title border-topbottom">当前城市</div>
                <div class="button-list">
                    <div class="button-wrapper">
                        <div class="button">北京</div>
                    </div>
                </div>
            </div>
            <div class="area">
                <div class="title border-topbottom">热门城市</div>
                <div class="button-list">
                    <div class="button-wrapper" v-for="item of hotCities" :key="item.id">
                        <div class="button">{{item.name}}</div>
                    </div>
                </div>
            </div>
            <div
                class="area"
                v-for="(item,key) of cities"
                :key="key"
                :ref="key"
                >
                <div class="title border-topbottom">{{key}}</div>
                <div class="item-list">
                    <div
                        class="item border-bottom"
                        v-for="innerItem of item"
                        :key="innerItem.id"
                    >{{innerItem.name}}</div>
                </div>
            </div>
        </div>
    </div>
</template>

<script>
// 引入better-scroll插件
import Bscroll from ‘better-scroll‘
export default{
    name:‘CityList‘,
    props:{
        hotCities:Array,
        cities:Object,
        letter: String
    },
    // dom挂载完毕之后执行.
    mounted(){
        // ref="wrapper" ref可以帮我们获取dom.
        this.scroll = new Bscroll(this.$refs.wrapper)
    },
    // 侦听器
    watch:{
        // 监听letter的变化。
        letter(){
            // console.log(‘兄弟组件收到了letter:‘,this.letter)
            if(this.letter){
                // 点击到哪个字母,div区域就显示哪一块内容。$refs[key]
                const element = this.$refs[this.letter][0];  // 注意:这是一个数组。不是一个元素。不能直接传给滚动对象。后面加一个0就好了。
                console.log(element);

                this.scroll.scrollToElement(element);  // 传的参数必须是dom元素。
            }
        }
    }
}

</script>

<style lang="stylus" scoped>
    .border-topbottom
        &:before
            border-color:#ccc
        &:after
            border-color:#ccc

    .border-bottom
        &:before
            border-color:#ccc

    .list
        overflow:hidden
        position:absolute
        top:1.58rem
        left:0
        right:0
        bottom:0

        .title
            line-height:.54rem
            background:#eee
            padding-left:.2rem
            color:#666
            font-size:.26rem

        .button-list
            overflow:hidden
            padding:.1rem .6rem .1rem .1rem

            .button-wrapper
                float:left
                width:33.33%
                .button
                    margin:.1rem
                    padding:.1rem 0
                    text-align:center
                    border:.02rem solid #ccc
                    border-radius:.06rem
        .item-list
            .item
                line-height:.76rem
                padding-left:.2rem

</style>

原文地址:https://www.cnblogs.com/c-x-m/p/10047014.html

时间: 2024-10-30 08:39:45

兄弟组件通信及滚动逻辑的相关文章

vue2.0 父子组件通信 兄弟组件通信

父组件是通过props属性给子组件通信的来看下代码: 父组件: <parent> <child :child-com="content"></child> //注意这里用驼峰写法哦 </parent> data(){ return { content:'sichaoyun' }; } 子组件通过props来接受数据 第一种方法 props: ['childCom'] 第二种方法 props: { childCom: String //这里

vue2.0s中eventBus实现兄弟组件通信

在vue1.0中,组件之间的通信主要通过vm.$dispatch沿着父链向上传播和用vm.$broadcast向下广播来实现.然而在vue2.0中,已经废除了这种用法. vuex加入后,对组件之间的通信有了更加清晰的操作,对于中大型的项目来说,一开始就把vuex的使用计划在内是明智的选择. 然而在一些小型的项目,或者说像我这样写到一半才发现vue2.0用不了$.broadcast和$dispatch的人来说,就需要一个比较便捷的解决方法.那么,eventBus的作用就体现出来了. 主要是现实途径

vue兄弟组件通信

所有需要通信的组件共用一个事件对象.new Vue(),新new一个vue对象,然后所有组件都访问这个对象,通过这个对象$emit事件,也通过这个对象$on监听事件. 实现一:直接在单文件里面实例化根Vue的时候,在data里return一个属性,值为new Vue(),例如bus: new Vue() 在具体的组件页面上,直接用this.$root.bus.$emit('eventName')发送事件. 在另一个组件页面的mounted函数里面,用this.$root.bus.$on('eve

vue组件详解(三)——组件通信

组件之间通信可以用下图表示: 组件关系可分为父子组件通信.兄弟组件通信.跨级组件通信. 一.自定义事件 当子组件需要向父组件传递数据时,就要用到自定义事件. 子组件用$emit ()来触发事件,父组件用$on()来监昕子组件的事件. 父组件可以直接在子组件的自定义标签上使用v-on 来监昕子组件触发的自定义事件,如: <div id="app9"> <p>总数:{{total}}</p> <my-component9 @add="ge

第八 组件通信(组件传值)

一.组件通信(组件传值) 相关学习链接:https://www.cnblogs.com/vichily/p/6484152.html ////学习链接:https://www.cnblogs.com/web-record/p/10320765.html 学习链接:https://segmentfault.com/a/1190000015727078 组件间的传值: https://segmentfault.com/a/1190000013945457 1.1父子组件通信 父组件<子组件标签 :变

【React源码分析】组件通信、refs、key和ReactDOM

React源码系列文章,请多支持:React源码分析1 - 组件和对象的创建(createClass,createElement)React源码分析2 - React组件插入DOM流程React源码分析3 - React生命周期详解React源码分析4 - setState机制React源码分析5 -- 组件通信,refs,key,ReactDOMReact源码分析6 - React合成事件系统 1 组件间通信 父组件向子组件通信 React规定了明确的单向数据流,利用props将数据从父组件传

vue兄弟组件的传值eventbus

注:当在a.vue组件上触发点击事件时,就会触发bus上监听的事件,而bus事件监听在b.vue里面,这个时候就会触发b.vue 上的事件监听,而通过回调函数,就可以拿到a.vue组件传过来的数据,从而实现兄弟组件通信. ###~~bus.js import Vue from "vue" export default new Vue()parent.vue父组件 <template> <div id="app"> <avue>&l

vue 2 使用Bus.js进行兄弟(非父子)组件通信 简单案例

vue2中废弃了$dispatch和$broadcast广播和分发事件的方法.父子组件中可以用props和$emit().如何实现非父子组件间的通信,可以通过实例一个vue实例Bus作为媒介,要相互通信的兄弟组件之中,都引入Bus,之后通过分别调用Bus事件触发和监听来实现组件之间的通信和参数传递. 首先需要在任意地方添加一个bus.js 在bus.js里面 写入下面信息 1 import Vue from 'vue' 2 export default new Vue; 在需要通信的组件都引入B

vue的$emit 与$on父子组件与兄弟组件的之间通信

本文主要对vue 用$emit 与 $on 来进行组件之间的数据传输. 主要的传输方式有三种: 1.父组件到子组件通信 2.子组件到父组件的通信 3.兄弟组件之间的通信 一.父组件传值给子组件 父组件给子组件传子,使用props //父组件:parent.vue <template> <div> <child :vals = "msg"></child> </div> </template> <script&