美文网首页
用vue实现楼层导航

用vue实现楼层导航

作者: alicemum | 来源:发表于2021-03-08 15:31 被阅读0次

    涉及的技术点

    1. created 生命周期函数
    2. 在vue中获取原生dom的vm.$refs
    3. vm.$nextTick方法
    4. 监听器watch

    created 生命周期函数

    created生命周期钩子中常发起ajax请求
    created是在数据注入之后,页面渲染之前自动触发的

    Vue实例化的过程

    1. 初始化生命周期函数
    2. 注入数据data,methods,computed,watch
    3. 自动调用created
    4. 读取模板,编译后视图渲染
    5. 当响应式数据发生改变时,重新编译并渲染视图

    在vue中获取原生dom的vm.$refs

    <div id="app">
        <button @click="getDom">获取dom</button>
        <ul ref="ulEl">
            <li v-for="(item,index) in list" ref="liEl">{{item}}</li>
        </ul>
        <p ref="pEl">这是一个段落</p>
    </div>
    
    methods: {
        getDom() {
            console.log(this.$refs);  // 对象类型
            console.log(this.$refs.ulEl); //ul的dom对象
            console.log(this.$refs.pEl); 
            console.log(this.$refs.liEl);  //数组
    
            // 获取索引为3的li距离页面顶端的偏移值
            console.log(this.$refs.liEl[3].offsetTop);
        }
    }
    

    vm.$nextTick方法

    在下次 DOM 更新循环结束之后执行延迟回调。在修改数据之后立即使用这个方法,获取更新后的 DOM。

    created() {
        console.log('created');
        setTimeout(() => {
            this.list = list;
            // 此时不能获取楼层的dom,因为数据改变后,到视图重新渲染,之间有延迟
            console.log(this.$refs.floor); //undefined
    
            // 在下次 DOM 更新循环结束之后执行延迟回调。在修改数据之后立即使用这个方法,获取更新后的 DOM。
            this.$nextTick(()=>{
                console.log('$nextTick');
                // console.log(this.$refs.floor);  //可以正常获取dom
    
                //this.listHeight是在vue实例上添加一个新属性,但并不是响应式数据
                this.listHeight = this.$refs.floor.map(item=> item.offsetTop)
            })
        }, 1000)
    },
    

    监听器

    监听索引变化,索引值发生改变,则执行页面滚动

    案例完整代码

    数据

    let list = [
        {
            "title": "产品功能",
            "listData": [
                { "id": 1, "cont": "产品功能1" },
                { "id": 2, "cont": "产品功能2" },
                { "id": 3, "cont": "产品功能3" },
                { "id": 4, "cont": "产品功能4" }
            ]
        },
        {
            "title": "产品参数",
            "listData": [
                { "id": 1, "cont": "产品参数1" },
                { "id": 2, "cont": "产品参数2" },
                { "id": 3, "cont": "产品参数3" },
                { "id": 4, "cont": "产品参数4" },
                { "id": 5, "cont": "产品参数5" },
                { "id": 6, "cont": "产品参数6" }
            ]
        },
        {
            "title": "产品评价",
            "listData": [
                { "id": 1, "cont": "产品评价1" },
                { "id": 2, "cont": "产品评价2" },
                { "id": 3, "cont": "产品评价3" },
                { "id": 4, "cont": "产品评价4" },
                { "id": 5, "cont": "产品评价5" },
                { "id": 6, "cont": "产品评价6" }
            ]
        }
    ]
    

    模板

    <div id="app">
        <div class="loading" v-if="isShow">loading......</div>
        <ul class="tab" v-if="list.length">
            <li v-for="(item,index) in list" @click="toggle(index)">{{item.title}}</li>
        </ul>
        <div class="floor"  v-for="(item,index) in list" :class="classList[index]" ref="floor">
            <ul>
                <li v-for="(smallItem,index) in item.listData">id: {{smallItem.id}}--------标题: {{smallItem.cont}}</li>
            </ul>
        </div>
    </div>
    

    js代码

    let vm = new Vue({
            el: '#app',
            data: {
                curIndex: 0,
                list: [],
                isShow: true,
                classList: ['function','params','ratings']
            },
            // created生命周期钩子中常发起ajax请求
            // created是在数据注入之后,页面渲染之前自动触发的
            created() {
                console.log('created');
                setTimeout(() => {
                    console.log(list);
                    this.list = list;
                    this.isShow = false;
                    // 此时不能获取楼层的dom,因为数据改变后,到视图重新渲染,之间有延迟
                    console.log(this.$refs.floor); //undefined
    
                    // 在下次 DOM 更新循环结束之后执行延迟回调。在修改数据之后立即使用这个方法,获取更新后的 DOM。
                    this.$nextTick(()=>{
                        console.log('$nextTick');
                        // console.log(this.$refs.floor);  //可以正常获取dom
    
                        //this.listHeight是在vue实例上添加一个新属性,但并不是响应式数据
                        this.listHeight = this.$refs.floor.map(item=> item.offsetTop)
                    })
                }, 1000)
            },
            methods: {
                toggle(index) {
                    this.curIndex = index
                }
            },
            watch: {
                curIndex() {
                    console.log('切换一次');
                    window.scrollTo({
                        top: this.listHeight[this.curIndex],
                        behavior: "smooth"
                    })
                }
            }
        });
    

    相关文章

      网友评论

          本文标题:用vue实现楼层导航

          本文链接:https://www.haomeiwen.com/subject/soipqltx.html