用vue实现楼层导航

2021-03-08  本文已影响0人  alicemum

涉及的技术点

  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"
                })
            }
        }
    });
上一篇下一篇

猜你喜欢

热点阅读