用代码预测未来买房后的生活

背景

最近家里突然计划买房,打破了我攒钱到财务自由的规划。所以开始重新计算自己背了房贷之后的生活到底如何。

一开始通过笔记软件来进行未来收入支出推算。后来发现太过麻烦,任何一项收入支出的改动,都会影响到后续结余累计值的计算。

所以干脆发挥传统艺能,写网页!

逻辑

  • 假设当前年收入稳定不变,在 50 之后收入降低。
  • 通过 上一年结余 + 收入-房贷-生活支出-特殊情况支出 的公式得到累加计算每年的结余资金。
  • 通过修改特使事件来模拟一些如装修、买车的需求。
  • 最后预测下 30 年后的生活结余,从而可知未来的生活质量。

实现

首先,创建一个 HTML 文件 feature.html,然后咔咔一顿写。

html 复制代码
<!DOCTYPE html>
<html lang="zh-CN" dir="ltr">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width,initial-scale=1" />
    <link rel="icon" href="https://cn.vuejs.org/logo.svg" />
    <title>生涯模拟</title>
    <meta name="description" content="人生经费模拟器" />

    <script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>

    <style>
      body {
        margin: 0;
        padding: 0;
      }

      .content {
        background: #181818;
        height: 100vh;
      }

      .time-line {
        height: 100%;
        overflow: auto;
      }

      .time-line-item {
        position: relative;
        padding: 10px 40px;
      }

      .flex-wrap {
        display: flex;
        flex-direction: row;
        align-items: center;
      }

      .tli-year {
        line-height: 24px;
        font-size: 18px;
        font-weight: bold;
        color: #e5eaf3;
      }

      .tli-amount {
        font-size: 14px;
        color: #a3a6ad;
        margin: 0 20px;
      }

      .tli-description {
        margin-top: 6px;
        line-height: 18px;
        font-size: 12px;
        color: #8d9095;
      }

      .tli-description-event {
        color: #f56c6c;
      }
    </style>
  </head>
  <body>
    <div id="app">
      <div class="content">
        <div class="time-line">
          <div v-for="item in data" :key="item.year" class="time-line-item">
            <div class="flex-wrap">
              <span class="tli-year">{{ item.year }}年</span>
              <span class="tli-amount">¥{{ item.ammount / 10000 }} 万</span>
            </div>
            <div
              v-for="desc in item.descriptions"
              class="tli-description flex-wrap"
              :class="desc.normal ? '' : 'tli-description-event'">
              <span style="margin-right: 20px">{{ desc.name }}</span>
              <span v-show="desc.ammount">{{ desc.ammount }}</span>
            </div>
          </div>
        </div>
      </div>
    </div>

    <script>
      const { createApp, ref, onMounted } = Vue;

      const config = {
        price: 6000000, // 房价
        startYear: 2023, // 开始还贷年份
        oldYear: 2041, // 老龄后收入降低
        startAmount: 100000, // 剩余资金
        income: 312000, // 年收入
        loan: 180000, // 年贷款
        live: 84000, // 年支出
        // 生活事件
        descriptions: [
          { year: 2024, ammount: 0, name: "大女儿一年级" },
          { year: 2026, ammount: 0, name: "小女儿一年级" },
          { year: 2028, ammount: 0, name: "老爸退休" },
          { year: 2026, ammount: -300000, name: "装修" },
          { year: 2031, ammount: -300000, name: "买车" },
          // { year: 2035, ammount: 3500000, name: "老房子卖出" },
        ],
      };

      createApp({
        setup() {
          const data = ref([]);

          onMounted(() => {
            genData();
          });

          function genData() {
            const arr = [];
            const startYear = config.startYear;
            const endYear = startYear + 30;

            for (let year = startYear; year < endYear; year++) {
              if (year === startYear) {
                arr.push({
                  year,
                  ammount: config.startAmount,
                  descriptions: [
                    {
                      name:
                        "开始买房,房价" +
                        config.price / 10000 +
                        "万,首付" +
                        (config.price * 0.3) / 10000 +
                        "万",
                      ammount: 0,
                    },
                  ],
                });
              } else {
                const latestAmount = arr[arr.length - 1].ammount;

                const filterDescs = config.descriptions.filter(
                  (item) => item.year === year
                );

                let descAmount = 0;
                if (filterDescs.length > 0) {
                  descAmount = filterDescs
                    .map((item) => item.ammount)
                    .reduce((acc, val) => acc + val);
                }

                const income =
                  year <= config.oldYear ? config.income : config.income * 0.8;

                arr.push({
                  year,
                  ammount:
                    latestAmount +
                    income -
                    config.loan -
                    config.live +
                    descAmount,
                  descriptions: [
                    {
                      name: "月收入",
                      ammount: income / 12,
                      normal: true,
                    },
                    {
                      name: "月贷款",
                      ammount: -config.loan / 12,
                      normal: true,
                    },
                    {
                      name: "月支出",
                      ammount: -config.live / 12,
                      normal: true,
                    },
                    {
                      name: "月结余",
                      ammount: (income - config.loan - config.live) / 12,
                      normal: true,
                    },
                    ...filterDescs,
                  ],
                });
              }
            }

            data.value = arr;
          }

          return {
            data,
          };
        },
      }).mount("#app");
    </script>
  </body>
</html>

PS: 之所以用 vue 呢是因为写起来顺手且方便(小工具而已,方便就行。不必手撕原生 JS DOM)。

效果

通过修改 config 中的参数来定义生活中收支的大致走向。外加一些标注和意外情况的支出。得到了下面这个图。

结论

  • 倘若过上房贷生活,那么家里基本一直徘徊在没钱的边缘,需要不停歇的工作,不敢离职。压力真的很大。30 年后除了房子其实没剩下多少积蓄了。
  • 修改配置,将房贷去掉,提高生活支出,那么 30 年后大概能存下 500w 的收入。

以上没有算通货膨胀和工资的上涨,这个谁也说不准。只是粗浅的计算。

所以,感觉上买房真的是透支了未来长期生活质量和资金换来的。也不知道买房的决定最终会如何。

相关推荐
吕彬-前端7 分钟前
使用vite+react+ts+Ant Design开发后台管理项目(二)
前端·react.js·前端框架
小白小白从不日白28 分钟前
react hooks--useCallback
前端·react.js·前端框架
恩婧36 分钟前
React项目中使用发布订阅模式
前端·react.js·前端框架·发布订阅模式
mez_Blog37 分钟前
个人小结(2.0)
前端·javascript·vue.js·学习·typescript
珊珊而川1 小时前
【浏览器面试真题】sessionStorage和localStorage
前端·javascript·面试
森叶1 小时前
Electron 安装包 asar 解压定位问题实战
前端·javascript·electron
drebander1 小时前
ubuntu 安装 chrome 及 版本匹配的 chromedriver
前端·chrome
软件技术NINI1 小时前
html知识点框架
前端·html
深情废杨杨1 小时前
前端vue-插值表达式和v-html的区别
前端·javascript·vue.js
GHUIJS1 小时前
【vue3】vue3.3新特性真香
前端·javascript·vue.js