关于获取高度的问题

关于获取高度的问题

问题描述:

为什么获取的高度为0?

相关代码:

​<template>
<div class="shop">
<Header>
<div class="shop_header">
<div class="back iconfont">&#xe603;</div>
<Search class="shop_search" message="请输入商品名称搜索" />
</div>
</Header>
<ShopInfo :item="item" :hideBorder="true" v-show="item.imgUrl" class="shop_title" />
<div class="shop_content">123</div>
<div class="shop_floor"></div>
</div>
</template>

<script>
import { onMounted, reactive, toRefs } from "vue";
import { useRoute } from "vue-router";
import { GET } from "../../utils/requset";
import Header from "@/components/Header/Header";
import Search from "@/components/Search/Search";
import ShopInfo from "@/components/ShopInfo/ShopInfo";

const useShopInfoEffect = () => {
const route = useRoute();
const data = reactive({ item: {} });
const shopId = route.params.id;
const getItemData = async () => {
const result = await GET(`/shop/${shopId}`);
if (result?.errno === 0 && result?.data) {
// data.item = result.data;
switch (shopId) {
case "1":
data.item = result.data.a;
// data.item = result.data[1];
break;
case "2":
data.item = result.data.b;
break;
case "3":
data.item = result.data.c;
break;
case "4":
data.item = result.data.d;
break;
case "5":
data.item = result.data.e;
break;
}
}
};
const { item } = toRefs(data);
return { item, getItemData };
};

const a = () => {
console.log(document.querySelector(".shop_title").clientHeight);
};

export default {
name: "Shop",
components: { Header, Search, ShopInfo },
setup() {
const { item, getItemData } = useShopInfoEffect();
getItemData();
onMounted(a);
return { item };
},
};
</script>

<style lang="scss" scoped>
.shop {
display: flex;
flex-direction: column;
width: 100%;

.back {
font-size: 0.3rem;
text-align: center;
}

&_header {
display: flex;
align-items: center;
height: 100%;
padding: 0 0.12rem;
}
&_search {
flex: 1;
}

&_title {
// position: fixed;
background: #fff;
padding: 0.1rem 0.12rem 0;
}

&_content {
height: 10rem;
overflow-y: auto;
}

&_floor {
position: fixed;
bottom: 0;
width: 100%;
height: 0.5rem;
background: #ffffff;
box-shadow: 0 -1px 1px 0 #f1f1f1;
}
}
</style>


正在回答 回答被采纳积分+1

登陆购买课程后可参与讨论,去登陆

2回答
好帮手慕久久 2021-07-19 18:58:56

同学你好,由于老师没有header等组件,并且接口地址等与同学的不一致,所以我调整了同学的代码后,才进行的测试。测试结果是可以执行方法a的:

http://img1.sycdn.imooc.com//climg/60f550fd090ae19112460622.jpg

http://img1.sycdn.imooc.com//climg/60f5510b090ab81710510600.jpg

建议同学下载源码,将如下代码(调整后的同学代码),替换源码中shop.vue组件,并启动项目测试一下:

<template>

  <div class="shop">

    <Header>

      <!-- 结构调整了一下 -->

      <div class="shop_header">

        <div class="back iconfont">&#xe603;</div>

        <Search class="shop_search" message="请输入商品名称搜索" />

      </div>

      <ShopInfo

        :item="item"

        :hideBorder="true"

        v-show="item.imgUrl"

        class="shop_title"

        ref="reference"

      />

    </Header>

    <div class="shop_content">123</div>

    <div class="shop_floor"></div>

  </div>

</template>


<script>

import { onUpdated, reactive, toRefs } from 'vue'

import { useRoute } from 'vue-router'

// 引入的内容 和路径 调整了一下

import { get } from '../../utils/request'

import ShopInfo from '../../components/ShopInfo'


const useShopInfoEffect = () => {

  const route = useRoute()

  const data = reactive({ item: {} })

  const shopId = route.params.id

  const getItemData = async () => {

    // 调整接口

    const result = await get(`/api/shop/${shopId}`)

    if (result?.errno === 0 && result?.data) {

      // 调整数据

      data.item = result.data

      // switch (shopId) {

      //   case "1":

      //     data.item = result.data.a;

      //     // data.item = result.data[1];

      //     break;

      //   case "2":

      //     data.item = result.data.b;

      //     break;

      //   case "3":

      //     data.item = result.data.c;

      //     break;

      //   case "4":

      //     data.item = result.data.d;

      //     break;

      //   case "5":

      //     data.item = result.data.e;

      //     break;

      // }

    }

  }

  const { item } = toRefs(data)

  return { item, getItemData }

}


const a = () => {

  alert('123')

  // 获取页面中,存在的元素的clientHeight

  console.log(document.querySelector('.shop_title').clientHeight)

}


export default {

  name: 'Shop',

  components: { ShopInfo },  /* 将不存在的组件去掉 */

  setup() {

    const { item, getItemData } = useShopInfoEffect()

    getItemData()

    onUpdated(a)

    return { item }

  },

}

</script>


<style lang="scss" scoped>

.shop {

  display: flex;

  flex-direction: column;

  position: absolute;

  top: 0.85rem;

  left: 0;

  right: 0;


  width: 100%;


  .back {

    font-size: 0.3rem;

    text-align: center;

  }


  &_header {

    display: flex;

    align-items: center;

    height: 100%;

    padding: 0 0.12rem;

  }

  &_search {

    flex: 1;

  }


  &_title {

    background: #fff;

    padding: 0.1rem 0.12rem 0;

  }


  &_content {

    height: 10rem;

    overflow-y: auto;

  }


  &_floor {

    position: fixed;

    bottom: 0;

    width: 100%;

    height: 0.5rem;

    background: #ffffff;

    box-shadow: 0 -1px 1px 0 #f1f1f1;

  }

}

</style>

然后对照源码,检查一下自己的代码。

祝学习愉快!

  • 提问者 龙同學 #1

    嗯,如果把ShiopInfo组件移出Header组件onUpdate()就起作用能读取高度了,如果被Header组件包裹就读取不到,这是为什么呢?

    2021-07-19 22:58:39
  • 好帮手慕久久 回复 提问者 龙同學 #2

    同学你好,使用Header组件包裹ShopInfo后,ShopInfo的更新操作就会被Header组件接管,所以更新操作就无法在Shop组件中监听了。此时可以在Header组件中,监听ShopInfo的更新,例如:

    http://img1.sycdn.imooc.com//climg/60f63ba109ac382f08170585.jpg

    http://img1.sycdn.imooc.com//climg/60f63bda09d0a8f516390443.jpg

    如果同学想在ShopInfo中使用该数据,则建议调整html结构,不要将ShopInfo包裹在Header中。

    祝学习愉快!

    2021-07-20 10:59:41
  • 提问者 龙同學 回复 好帮手慕久久 #3

    嗯,我后面改结构了,但有出现新问题了。当我返回主页重新点击商铺进去详情页面后,获取的高度就没有了,只有第一次进入详情页能获取到高度,后面就需要再刷新一次才能获取到高度,这是由于我暂时把所有详情页面的数据都写在同一个地址,导致onUpdate获取的数据没有得到更新,onUpdate就不会执行了是这样吗?如果是该怎么解决(我知道后面学习数据库后会有解决办法,但我想知道就目前进度能有什么解决办法,望老师解答疑惑)?


    第二次进入详情页且没刷新↓                                         刷新后↓

    http://img1.sycdn.imooc.com//climg/60f69624097fe1b506201037.jpg                                       http://img1.sycdn.imooc.com//climg/60f69660091b0e1c05621003.jpg

    主体地址:

    https://www.fastmock.site/mock/e7fafd87b10817643d0f2e2e0cdf800f/cjddj

    shop 页代码:

    <template>
      <div class="shop">
        <Shop-Header class="shopheader" />
        <div class="shop_content">
          <div class="shop_content_category">123</div>
        </div>
        <div class="shop_floor"></div>
      </div>
    </template>

    <script>
    import {} from "vue";
    import ShopHeader from "./Header/header";

    export default {
      name: "Shop",
      components: { ShopHeader },
      setup() {},
    };
    </script>

    <style lang="scss" scoped>
    @import "../../style/mixin.scss";

    .shop {
      width: 100%;
      @include layout;

      &_title {
        background: #fff;
        padding: 0.1rem 0.12rem 0;
        z-index: 99;
      }

      &_content {
        overflow-y: auto;
      }

      &_floor {
        position: fixed;
        bottom: 0;
        width: 100%;
        height: 0.5rem;
        background: #ffffff;
        box-shadow: 0 -1px 1px 0 #f1f1f1;
      }
    }
    </style>

    shopHeader 组件代码:

    ​<template>
    <header class="shop_wrapper">
    <div class="shop_header">
    <div class="shop_header_back iconfont" @click="handleBackClick">&#xe603;</div>
    <Search class="shop_header_search" message="请输入商品名称搜索" />
    </div>
    <ShopInfo :item="item" :hideBorder="true" v-show="item.imgUrl" class="shop_title" />
    </header>
    </template>

    <script>
    import { onUpdated, reactive, toRefs } from "vue";
    import { useRoute, useRouter } from "vue-router";
    import { GET } from "../../../utils/requset";
    import Search from "@/components/Search/Search";
    import ShopInfo from "@/components/ShopInfo/ShopInfo";

    const useShopInfoEffect = () => {
    const route = useRoute();
    const data = reactive({ item: {} });
    const shopId = route.params.id;
    const getItemData = async () => {
    const result = await GET(`/shop/${shopId}`);
    if (result?.errno === 0 && result?.data) {
    // data.item = result.data;
    switch (shopId) {
    case "1":
    data.item = result.data.a;
    // data.item = result.data[1];
    break;
    case "2":
    data.item = result.data.b;
    break;
    case "3":
    data.item = result.data.c;
    break;
    case "4":
    data.item = result.data.d;
    break;
    case "5":
    data.item = result.data.e;
    break;
    }
    }
    };
    const { item } = toRefs(data);
    return { item, getItemData };
    };

    const useBackRouterEffect = () => {
    const router = useRouter();
    const handleBackClick = () => {
    router.back();
    };
    return { handleBackClick };
    };

    const fixPositionTopEffect = async () => {
    // setTimeout(() => {
    // const b = document.querySelector(".shop_title");
    // console.log(b);
    // }, 100);
    const shopWrapperHeight = document.querySelector(".shop_wrapper").clientHeight;
    const shopEl = document.querySelector(".shop");
    shopEl.style.top = `${shopWrapperHeight / 100}rem`;
    console.log(shopWrapperHeight);
    };

    export default {
    name: "ShopHeader",
    components: { Search, ShopInfo },
    setup() {
    const { item, getItemData } = useShopInfoEffect();
    const { handleBackClick } = useBackRouterEffect();
    getItemData();
    onUpdated(fixPositionTopEffect);
    return { item, handleBackClick };
    },
    };
    </script>

    <style lang="scss" scoped>
    .shop_wrapper {
    position: fixed;
    top: 0;
    width: 100%;
    padding: 0 0.12rem;
    }

    .shop_header {
    display: flex;
    align-items: center;
    height: 0.5rem;
    background: #fff;

    &_back {
    font-size: 0.3rem;
    text-align: center;
    }

    &_search {
    flex: 1;
    }
    }

    .shop_title {
    box-shadow: 0px 4px 10px 0px #d1d1d1;
    }
    </style>


    2021-07-20 17:34:55
好帮手慕久久 2021-07-19 16:10:18

同学你好,解答如下:

1、div.shop_title初始时,并没有内容,此时高度是0。当异步获取到数据,并渲染到页面上之后,div.shop_title才会有高度。由于onMounted事件触发时,div.shop_title中并没有真实的内容,所以获取到的高度是0。

可以使用定时器延时测试一下:

http://img1.sycdn.imooc.com//climg/60f5324b09258fe107540218.jpg

http://img1.sycdn.imooc.com//climg/60f5325a0972d1a408480121.jpg

http://img1.sycdn.imooc.com//climg/60f532640946e4bd13490454.jpg

因此,建议将​onMounted换成onUpdated,即在页面发生更新后,再获取高度(获取到数据并渲染到页面上后,会触发onUpdated):

http://img1.sycdn.imooc.com//climg/60f532a50969f44007710350.jpg

http://img1.sycdn.imooc.com//climg/60f532ae09bde65110810527.jpg

2、另外,要注意,​div.shop_title的结构是利用数据渲染的,所以一定要保证数据是正确的,

http://img1.sycdn.imooc.com//climg/60f533120954f2a807770807.jpg

祝学习愉快!


  • 提问者 龙同學 #1

    老师,我改成onUpdate了没反应呀?

    <template>
    <div class="shop">
    <Header>
    <div class="shop_header">
    <div class="back iconfont">&#xe603;</div>
    <Search class="shop_search" message="请输入商品名称搜索" />
    </div>
    <ShopInfo :item="item" :hideBorder="true" v-show="item.imgUrl" class="shop_title" ref="reference" />
    </Header>
    <div class="shop_content">123</div>
    <div class="shop_floor"></div>
    </div>
    </template>

    <script>
    import { onUpdated, reactive, toRefs } from "vue";
    import { useRoute } from "vue-router";
    import { GET } from "../../utils/requset";
    import Header from "@/components/Header/Header";
    import Search from "@/components/Search/Search";
    import ShopInfo from "@/components/ShopInfo/ShopInfo";

    const useShopInfoEffect = () => {
    const route = useRoute();
    const data = reactive({ item: {} });
    const shopId = route.params.id;
    const getItemData = async () => {
    const result = await GET(`/shop/${shopId}`);
    if (result?.errno === 0 && result?.data) {
    // data.item = result.data;
    switch (shopId) {
    case "1":
    data.item = result.data.a;
    // data.item = result.data[1];
    break;
    case "2":
    data.item = result.data.b;
    break;
    case "3":
    data.item = result.data.c;
    break;
    case "4":
    data.item = result.data.d;
    break;
    case "5":
    data.item = result.data.e;
    break;
    }
    }
    };
    const { item } = toRefs(data);
    return { item, getItemData };
    };

    const a = () => {
    alert("123");
    console.log(document.querySelector(".header").clientHeight);
    };

    export default {
    name: "Shop",
    components: { Header, Search, ShopInfo },
    setup() {
    const { item, getItemData } = useShopInfoEffect();
    getItemData();
    onUpdated(a);
    return { item };
    },
    };
    </script>

    <style lang="scss" scoped>
    .shop {
    display: flex;
    flex-direction: column;
    position: absolute;
    top: 0.85rem;
    left: 0;
    right: 0;

    width: 100%;

    .back {
    font-size: 0.3rem;
    text-align: center;
    }

    &_header {
    display: flex;
    align-items: center;
    height: 100%;
    padding: 0 0.12rem;
    }
    &_search {
    flex: 1;
    }

    &_title {
    background: #fff;
    padding: 0.1rem 0.12rem 0;
    }

    &_content {
    height: 10rem;
    overflow-y: auto;
    }

    &_floor {
    position: fixed;
    bottom: 0;
    width: 100%;
    height: 0.5rem;
    background: #ffffff;
    box-shadow: 0 -1px 1px 0 #f1f1f1;
    }
    }
    </style>

    http://img1.sycdn.imooc.com//climg/60f54c60091b9b1f19831074.jpg

    2021-07-19 17:57:25
问题已解决,确定采纳
还有疑问,暂不采纳

恭喜解决一个难题,获得1积分~

来为老师/同学的回答评分吧

0 星
请稍等 ...
意见反馈 帮助中心 APP下载
官方微信

在线咨询

领取优惠

免费试听

领取大纲

扫描二维码,添加
你的专属老师