vue.js 中自动填充 div 高度为 100%

2017-08-22 23:03:11
window.client H:900px
 |
 v
+--------------------------+
| navbar                   |
+------+-------------------+
|      |                   |
|      |                   |
| side |   main H:200px    |
| bar  |                   |
|      |                   |
+------+-------------------+
|                          |
|   FPzone                 |
|                          |
+--------------------------+

这种问题在前端中属于典型案例,如(图)所示,main 的高度撑死了就只有 200px 且为灰色底,但浏览器 window.client 高度有 900px,这 tMd 就非常尴尬了。搞得 FPzone 那块地方是白色的,巨丑无比。所以必须想办法技计算出一个高度,赋给 main。

jQuery 时代的解决方案

这种事情在 jQuery 时代是个小事情,几行代码写个 setMaxHeigt() 搞定了:

// 伪代码
const mH = getMainHeight();
const cH = getClientHeight();

if (mH < cH) {
    mH.style.height = cH;
}

vue.js 时代的解决方案

但是到了 vue.js 时代,…… *&……¥%#@ 好多东西说不清楚,听我慢慢道来(今天差点给跪了😖)

  • 一开始想着写个 computed 实时计算一下 mainHeight,但是失败了,因为进来第一次是 computed 出来了,但由于 vue.js 是 SPA,不全局刷新 dom,所以 router 到另外的模块就没反应了!这……
  • 既然 computed 只跑一次,那我 watch 还不行,watch 什么呢?当然是 $router,不过 watch $router 出来的 mainHeight 都是上一个页面的 heightValue,这……
  • 中途还试了很多方法,包括走回 jQuery 老路,但涉及 router 刷新问题,一样失败了,直到我想起 vue.js 有个生命周期表。

try 半天,到最后其实还是弄出来,分别在 mounted() 和 updated() 放上这个 autoSetLayoutMainHeight()。

特别要说的是 updated(),vue.js 相必大家常用的就两个,一个 created(),一个 mounted(),别的要么不知道怎么用,要么就是没有场景让你知道怎么用。我属于第二种。😢

话不多说,贴代码:

data() {
    return {
        layoutMainStyle: {
            height: 'auto',
        },
    };
},
mounted() {
    this.autoSetLayoutMainHeight();
},
updated() {
    this.autoSetLayoutMainHeight();
},
methods: {
    autoSetLayoutMainHeight() {
        const layoutMainEl = document.getElementById('layout__main');

            // 初始化 mainHeight,避免出现 mainHeight 附上 clientHeight 的值就一直保持不变
            layoutMainEl.style.height = 'auto';

            // 计算 mainHeight 新高度
            const clientHeight = document.body.clientHeight;
            const layoutMainHeight = layoutMainEl.offsetHeight;

            if (layoutMainHeight < clientHeight) {
                layoutMainEl.style.height = `${clientHeight}px`;
            }
    },
},

这里顺带贴一下 vue 生命周期解释

// 在数据初始化之前被调用(实例创建之后)
beforeCreate() {},

// 在数据初始化之后被调用(页面进来时立即调用,created 是第一选择)
created() {},

// 在组件渲染之前被调用(数据渲染之前)
// 比如要色彩渲染可以在这里写
beforeMount() {},

// 整个实例被创建完成后被调用(生命周期用的最多的就是 mounted)
// 实例创建完成、数据初始化、渲染页面数据后,才被调用,这个时候就可以在 mounted 里写 Dom 操作了
mounted() {},

// 在数据改变时被调用
// 比如: total = 0 , 然后手动把num++; 就会执行此方法
beforeUpdate() {},

// 数据被更新之后
// 比如:total 值改变之后
updated() {},

// keep-alive 组件激活时调用(路由切换时被调用)
// 注意要配合 keep-alive 使用才会被调用
activated() {},

// keep-alive 组件停用时调用
// 也可以理解成在路由切换的时候会自动停用组件
deactivated() {},

// 实例销毁之前被调用
// 这个方法适用于把 new Vue({}) 赋值给一个变量时,如 var vm = new Vue({}),然后用vm.$destroy() 方法销毁这个实例
beforeDestroy() {},

// 实例销毁之后被调用
// 一般情况下,在页面切换路由时,会自动销毁组件
destroyed() {},

- EOF -