【别贪心】static_vue_ele_blog

这个是作者大大写的一个自适应的博客网站,我们可以看下是怎么实现的
先放下作者大大的github地址:https://github.com/youyougu-me/static_vue_ele_blog
接下来我们一起来欣赏项目哇

//main.js

import Vue from "vue";
import App from "./App.vue";
import router from "./router/index";
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
import "./icons";
import vueSmoothScroll from 'vue-smooth-scroll'
Vue.use(vueSmoothScroll)
Vue.use(ElementUI);
Vue.config.productionTip = false;
new Vue({
  router,
  render: h => h(App)
}).$mount("#app");


main.js中引用了一个让页面可以很丝滑的vue-smooth-scroll组件

接下来我们来看app.vue

//app.vue
<template>
  <div id="app">
    <router-view v-if="isRouterAlive"></router-view>
  </div>
</template>
<script>
export default {
  name: "App",
  provide() {
    //父组件中通过provide来提供变量,在子组件中通过inject来注入变量。
    return {
      reload: this.reload
    };
  },
  data() {
    return {
      isRouterAlive: true //控制视图是否显示的变量
    };
  },
  methods: {
    reload() {
      this.isRouterAlive = false; //先关闭,
      this.$nextTick(function() {
        this.isRouterAlive = true; //再打开
      });
    }
  },
  mounted() {}
};
</script>


<style lang="scss">
#app {
   100%;
}
</style>

app.vue中也很神奇,使用

  provide() {
    //父组件中通过provide来提供变量,在子组件中通过inject来注入变量。
    return {
      reload: this.reload
    };
  },

这个是想实现点击当前刷新路由,可用。
接下来我们来看router.js

import Vue from "vue";
import VueRouter from "vue-router";
import Layout from '@/views/Layout'

Vue.use(VueRouter);
//默认路由
export const defaultRoutes = [
  {
    path: "/",
    redirect: "/console",
  },
  {
    path: "/console",
    name: "Console",
    redirect: "index",
    meta: {
      name: "控制台",
      icon: 'console'
    },
    component: Layout,
    children: [
      {
        path: "/index",
        name: "Index",
        meta: {
          name: "首页"
        },
        component: () => import("../views/Console/index.vue")
      }
    ]

  },
  //为防止报错,匹配的*号404应该放在动态路由的最后
  {
    path: "*",
    redirect: '/',
    hidden: true,
  }
]

// 解决ElementUI导航栏中的vue-router在3.0版本以上重复点菜单报错问题
const originalPush = VueRouter.prototype.push
VueRouter.prototype.push = function push(location) {
  return originalPush.call(this, location).catch(err => err)
}
const router = new VueRouter({
  routes: defaultRoutes
});

export default router;

这个router.js那里其实也是有一个小细节在的,我就是因为没有留意到,然后看下面的代码就有些迷失了。
跟我一起看这个细节,layout.vue组件吧.

<template>
  <div>
    <!-- 普通定位,高度为视口大小 -->
    <LayoutHeader />
    <!-- 普通定位,左浮动,固定宽度,设置左margin -->
    <LayoutMain />
    <!-- <div id="blog_ex" class="hehehe" @click="toWowo">wowow喔喔</div> -->
    <!-- 刚开始是relative,之后fixed -->
    <LayoutNav />
    <!-- 普通定位,左浮动,固定宽度,设置左margin -->
    <Foot />
  </div>
</template>

<script>
import LayoutHeader from "./Components/Header";
import LayoutMain from "./Components/Main";
import LayoutNav from "./Components/Nav";
import Foot from "./Components/foot";
export default {
  data() {
    return {};
  },
  methods: {
    toWowo() {
      let anchorElement = document.getElementById("blog_ex");
      if (anchorElement) {
        anchorElement.scrollIntoView();
      }
    }
  },
  created() {},
  mounted() {},
  components: {
    LayoutHeader,
    LayoutMain,
    LayoutNav,
    Foot
  }
};
</script>
<style lang="scss" scoped>
.hehehe {
  height: 2000px;
  float: left;
  margin-left: 320px;
   calc(100% - 320px);
  padding-left: 30px;
  padding-top: 40px;
  position: relative;
  box-sizing: border-box;
  background-color: darkcyan;
}
</style>

复习一个小知识点
Element.scrollIntoView() 方法让当前的元素滚动到浏览器窗口的可视区域内。

//Header.vue
<template>
  <div id="home">
    <!-- 全屏背景,大父级,相对定位 -->
    <div class="bgc">
      <!-- 控制上下滑动浮动图标 -->
      <transition>
        <!-- div与icon一样大小 -->
        <div v-show="showFlag" class="icon_div">
          <a href="#blog_main" v-smooth-scroll style="100px;height:100px;display:block;">
            <svg-icon iconClass="pull" class="pull"></svg-icon>
          </a>
        </div>
      </transition>
      <!-- 斜标签 -->
      <div class="fork-me">
        <a class="fork-me-link">
          <span class="fork-me-text">No pain, no gain</span>
        </a>
      </div>
      <!-- 头像及名字 -->
      <div class="avatar_box">
        <img src="../../../assets/images/avatar.png" alt class="avatar" />
        <div class="name">我背景离乡了好多年</div>
        <div class="typer">
          <Typer></Typer>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
import { move } from "@/utils/toolFunc.js";
import Typer from "@c/Typer";
export default {
  data() {
    return {
      //下拉浮动标志的显示控制
      showFlag: true
    };
  },
  methods: {
    //点击事件 实现点击浮动下拉图标,平滑滑动到主页开头部分(也是侧边栏的头)
    moveToHome() {
      //目标元素距离页面顶部的距离,在这里是恒定值
      let total = document.getElementById("blog_main").offsetTop;
      move(total);
    }
  },
  created() {
    //定时器
    const timer = setInterval(() => {
      this.showFlag = !this.showFlag;
    }, 1000);
    this.$once("hook:beforeDestroy", () => {
      clearInterval(timer);
    });
  },
  mounted() {},
  components: {
    Typer
  }
};
</script>
<style lang="scss" scoped>
@import "@/styles/fork.scss";
#home {
   100%;
  overflow: hidden;
  .bgc {
    // position: absolute;
    // top: 0;
    // left: 0;
    //  100%;
    // height: 100%;
    // z-index: -1;
    //======================
     100%;
    height: 100vh;
    position: relative;
    //======================
    background: #50616d url(../../../assets/images/background.jpg) no-repeat 50%
      scroll;
    background-size: cover;
  }
  //浮动图标
  .icon_div {
    position: absolute;
    left: 50%;
    transform: translateX(-50%);
    bottom: 100px;
    z-index: 1;
     100px;
    height: 100px;
    // background-color: red;
    text-align: center;
    line-height: 100px;
  }
  //头像及名字
  .avatar_box {
    // background-color: #ccc;
     300px;
    height: 500px;
    position: absolute;
    left: 50%;
    transform: translateX(-50%);
    top: 25%;
    .avatar {
       100px;
      margin: 0 auto;
      border-radius: 50%;
      opacity: 0.8;
    }
    .name {
      text-align: center;
      margin: 20px auto;
      color: #fff;
      font-size: 20px;
      opacity: 0.8;
    }
    .typer {
      // text-align: center;
      margin-left: 28px;
    }
  }
}
//======================动画
.v-enter,
.v-leave-to {
  opacity: 1;
  // transform: translateY(5px) !important;
  bottom: 80px !important;
}
.v-leave-active {
  transition: all 1s ease;
}

.v-enter-active {
  transition: all 1s ease;
}
</style>

光标的动画效果为

//Typer.vue
<template>
  <div class="typer">
    <div class="typer-content">
      <p class="typer-static">&nbsp;</p>
      <!-- 动态变化的内容-->
      <p class="typer-dynamic">
        <span class="cut">
          <span class="word" v-for="(letter,index) in words" :key="index">{{letter}}</span>
        </span>
        <!-- 模拟光标-->
        <span class="typer-cursor"></span>
      </p>
    </div>
  </div>
</template>


<script>
export default {
  data() {
    return {
      words: [], //字母数组push,pop的载体
      str: "那一年,我决定背井离乡", //str初始化
      letters: [], //str分解后的字母数组
      order: 1 //表示当前是第几句话
    };
  },
  watch: {
    //监听order值的变化,改变str的内容
    order(old, newV) {
      //   if (this.order % 4 == 1) {
      //     this.str = "那一天";
      //   } else if (this.order % 4 == 2) {
      //     this.str = "我背井离乡";
      //   } else if (this.order % 4 == 3) {
      //     this.str = "乡里人再也没喝上一口水";
      //   } else {
      //     this.str = "coding the web...";
      //   }
      // }
      if (this.order == 1) {
        this.str = "那一年,我决定背井离乡";
      } else if (this.order % 2 == 1) {
        this.str = "那一年,我决定背井离乡";
      } else {
        this.str = "乡里人再也没喝上一口水";
      }
    }
  },
  mounted() {
    //页面初次加载后调用begin()开始动画
    this.begin();
  },
  methods: {
    //开始输入的效果动画
    begin() {
      this.letters = this.str.split("");
      for (var i = 0; i < this.letters.length; i++) {
        setTimeout(this.write(i), i * 200);
      }
    },
    //开始删除的效果动画
    back() {
      let L = this.letters.length;
      for (var i = 0; i < L; i++) {
        setTimeout(this.wipe(i), i * 100);
      }
    },
    //输入字母
    write(i) {
      return () => {
        let L = this.letters.length;
        this.words.push(this.letters[i]);
        let that = this;
        /*如果输入完毕,在2s后开始删除*/
        if (i == L - 1) {
          setTimeout(function() {
            that.back();
          }, 2000);
        }
      };
    },
    //擦掉(删除)字母
    wipe(i) {
      return () => {
        this.words.pop(this.letters[i]);
        /*如果删除完毕,在300ms后开始输入*/
        if (this.words.length == 0) {
          this.order++;
          let that = this;
          setTimeout(function() {
            that.begin();
          }, 300);
        }
      };
    }
  }
};
</script>


<style scoped lang="scss">
.typer {
  margin-top: 2%;
  box-sizing: border-box;
}
.typer .typer-content {
  // font-weight: bold;
  font-size: 18px;
  display: flex;
  flex-direction: row;
  letter-spacing: 2px;
}
.typer-dynamic {
  position: relative;
}
.cut {
  color: #fff;
}
.typer-cursor {
  position: absolute;
  height: 100%;
   3px;
  top: 0;
  right: -10px;
  background-color: #e84d49;
  animation: flash 1.5s linear infinite;
}
</style>

Main.vue

//Main.vue
<template>
  <div id="blog_main">
    <!-- 移动端抽屉控制图标 -->
    <div
      :class="['draw_flagico',drawerFlag==true?'drawer_open':'drawer_close',fixedFlag==true?'haha':'']"
      @click="controlDrawer"
      ref="drawFlagico"
    >
      <svg-icon
        :iconClass="drawerFlag==true?'rightarrow':'list'"
        :class="drawerFlag==true?'rightarrow':'list'"
      />
    </div>
    <!-- 移动端抽屉 -->
    <el-drawer
      :visible.sync="drawerFlag"
      direction="ltr"
      :before-close="drawerHandleClose"
      :with-header="false"
      :wrapperClosable="true"
      :show-close="true"
      :size="'256px'"
    >
      <MyMenu @controlDrawer="controlDrawer"></MyMenu>
    </el-drawer>

    <!-- 可变内容 -->
    <div style="100%">
      <keep-alive>
        <router-view />
      </keep-alive>
    </div>
  </div>
</template>

<script>
import MyMenu from "./MyMenu";
export default {
  data() {
    return {
      drawerFlag: false,
      //页面滑出距离
      toTopDistance: "",
      //整屏幕距离
      fullHeight: document.documentElement.clientHeight,
      fixedFlag: false
    };
  },
  methods: {
    drawerHandleClose(done) {
      done();
    },
    //控制抽屉
    controlDrawer() {
      this.drawerFlag = !this.drawerFlag;
    },
    //获取页面滑出距离
    funx() {
      if (document.documentElement.scrollTop != undefined) {
        this.toTopDistance = document.documentElement.scrollTop;
        return;
      }
      if (document.body.scrollTop != undefined) {
        this.toTopDistance = document.body.scrollTop;
        return;
      }
      if (window.pageYOffset != undefined) {
        this.toTopDistance = window.pageYOffset;
        return;
      }
    }
  },
  mounted() {
    // this.$refs.drawFlagico.style.top = this.fullHeight + "px";
    const that = this;
    //页面一旦改变便会执行
    //但是刷新不会执行
    window.onresize = () => {
      return (() => {
        window.fullHeight = document.documentElement.clientHeight;
        that.fullHeight = window.fullHeight;
      })();
    };

    //监听滚动
    window.addEventListener("scroll", () => {
      this.funx();
      if (this.toTopDistance > this.fullHeight) {
        this.fixedFlag = true;
      } else {
        this.fixedFlag = false;
      }
    });
  },
  watch: {
    //优化获取屏幕高度的值
    fullHeight(val) {
      if (!this.timer) {
        this.fullHeight = val;
        this.timer = true;
        let that = this;
        setTimeout(function() {
          that.timer = false;
        }, 400);
      }
    }
  },
  components: {
    MyMenu
  }
};
</script>

<style lang="scss" scoped>
#blog_main {
  // height: 2000px;
  float: left;
  margin-left: 320px;
   calc(100% - 320px);
  padding-left: 30px;
  padding-top: 40px;
  padding-right: 30px;
  position: relative;
  box-sizing: border-box;

  // 小屏幕所见图标
  .draw_flagico {
    z-index: 9999;
    position: absolute;
     35px;
    height: 35px;
    border: 1px solid #409eff;
    text-align: center;
    line-height: 43px;
    border-radius: 50%;
    display: none;
    left: 15px;
    top: 6px;
    background-color: #fff;
    &:hover {
      border: 2px solid #409eff;
    }
    &.haha {
      position: fixed !important;
      top: 6px !important;
    }
  }

  .el-drawer {
    //小屏幕下图标可见,只有图标才可以打开抽屉、
    //不用设置大屏幕图标不可见
    //系统自带必须关闭抽屉才能操作
    // display: none !important;
  }

  //根据flag控制图标横向距离
  .drawer_open {
    left: 270px;
  }
  .drawer_close {
    left: 15px;
  }
}

//媒体查询
@media screen and (max- $--screen-sm-min) {
  //小屏幕
  #blog_main {
    margin-left: 0px;
     100%;
    //去掉左边距
    padding: 0 5px;
    // 控制抽屉图标可见
    .draw_flagico {
      display: block;
    }
    //抽屉可见
  }
}
</style>
//MyMenu.vue
<template>
  <div id="my_menu">
    <!-- 头像名字 -->
    <div class="info">
      <img src="@/assets/images/avatar.png" alt class="avatar" />
      <div class="name">我背井离乡了好多年</div>
    </div>
    <!-- 菜单 -->
    <el-menu
      :default-active="defaultActive"
      background-color="#fff"
      text-color="#2d2d2d"
      active-text-color="#f17c67"
      style="100%;position:absolute;"
    >
      <!-- key不能写在template这里 -->
      <template v-for="(item,index) in menus">
        <el-submenu :key="item.id" :index="index+''" v-if="item.children.length!==0">
          <!-- 一级菜单 -->
          <template slot="title">
            <!-- <i class="el-icon-location"></i> -->
            <!-- 那边item里没有icon的,这边也不会报错 -->
            <!-- <svg-icon :iconClass="iconsObj[item.id]" :className="iconsObj[item.id]" /> -->
            <span slot="title" style="padding-left:10px;">{{item.authName}}</span>
          </template>
          <!-- 子集菜单 -->
          <!-- index就是路径,组件内定的 -->
          <template v-for="subItem in item.children">
            <el-menu-item :key="subItem.id" :index="'/'+subItem.path">
              <a :href="'#'+subItem.meta.id">{{subItem.authName}}</a>
            </el-menu-item>
          </template>
        </el-submenu>

        <el-menu-item :key="item.id" :index="'/'+item.path" v-else class="noChildItem">
          <a
            :href="'#'+item.meta.id"
            v-smooth-scroll
            style="100%;height:100%;display:block;"
            @click="controlDrawer"
          >
            <svg-icon :iconClass="item.path" :className="item.path" />
            {{item.authName}}
          </a>
        </el-menu-item>
      </template>
    </el-menu>
    <!-- 尾部 -->
    <div class="footer">
      <!-- 社交 -->
      <Social />
      <!-- 版权 -->
      <Copyrights />
    </div>
  </div>
</template>

<script>
import Social from "./footer/Social";
import Copyrights from "./footer/Copyrights";
export default {
  data() {
    return {
      menus: [
        {
          id: 1,
          authName: "首页",
          path: "home",
          children: [],
          meta: {
            id: "home"
          }
        },
        {
          id: 2,
          authName: "关于",
          path: "about",
          children: [
            // {
            //   id: 111,
            //   authName: "概况",
            //   path: "about",
            //   children: []
            // }
          ],
          meta: {
            id: "about"
          }
        },
        {
          id: 3,
          authName: "经历",
          path: "works",
          children: [],
          meta: {
            id: "works"
          }
        },
        {
          id: 4,
          authName: "作品",
          path: "blog",
          children: [],
          meta: {
            id: "blog"
          }
        }
      ]
    };
  },
  methods: {
    //点击菜单时关闭抽屉
    controlDrawer() {
      this.$emit("controlDrawer");
    }
  },
  created() {},
  mounted() {},
  computed: {
    defaultActive: function() {
      const route = this.$route;
      return route.path;
    }
  },
  components: {
    Social,
    Copyrights
  }
};
</script>
<style lang="scss" scoped>
#my_menu {
  position: absolute;
  height: 100%;
   100%;
  //菜单
  .el-menu {
    // height: 100%;
    border-right: solid 0 #e6e6e6;
    .noChildItem {
      padding-left: 40px !important;
      border-bottom: 1px solid #ccc;
       80%;
      margin: 0 auto;
    }
  }
  //信息
  .info {
     100%;
    text-align: center;
    margin-bottom: 40px;
    .avatar {
       100px;
      border-radius: 50%;
      margin: 50px auto 10px;
    }
    .name {
      font-size: 16px;
    }
  }
  //尾部
  .footer {
     100%;
    position: absolute;
    bottom: 20px;
    left: 0;
  }
}
</style>
//foot.uve
<template>
  <div id="foot">
    <!-- 如果是响应式就不要把高度写死,这个type也不能是flex -->
    <el-row>
      <el-col :xs="24" :sm="8">
        <Copyrights />
      </el-col>
      <el-col :xs="24" :sm="8">
        <img src="../../../assets/images/avatar.png" alt class="avatar" />
      </el-col>
      <el-col :xs="24" :sm="8">
        <Social />
      </el-col>
    </el-row>
  </div>
</template>

<script>
import Social from "./footer/Social";
import Copyrights from "./footer/Copyrights";
export default {
  data() {
    return {};
  },
  methods: {},
  created() {},
  mounted() {},
  components: {
    Social,
    Copyrights
  }
};
</script>
<style lang="scss" scoped>
#foot {
  float: left;
  margin-left: 320px;
   calc(100% - 320px);
  position: relative;
  box-sizing: border-box;
  background-color: #eee;
  .avatar {
     50px;
    margin: auto auto;
    border-radius: 50%;
    opacity: 0.8;
  }
}

//媒体查询
@media screen and (max- $--screen-sm-min) {
  //小屏幕
  #foot {
    margin-left: 0px;
     100%;
    //去掉左边距
    padding: 10px 5px;
    .avatar{
        margin: 20px auto;
    }
  }
}

  //大屏幕
  @media screen and (min- $--screen-sm-min) {
    #foot {
      height: 100px;
      line-height: 100px;
      .avatar {
        margin-top: 25px;
      }
    }
  }
</style>
//Social.vue
<!-- 社交 -->

<template>
  <div id="social">
    <a href="https://github.com/youyougu-me" target="_blank">
      <svg-icon iconClass="github" class="github" />
    </a>
    <!-- <a href>
      <svg-icon iconClass="weixin" class="weixin" />
    </a>-->
    <el-popover placement="top-start" title="微信" width="100" trigger="hover">
      <img src="@/assets/images/weixin.jpg" alt style="100%;" />
      <a href slot="reference">
        <svg-icon iconClass="weixin" class="weixin" />
      </a>
    </el-popover>
    <a href="https://www.jianshu.com/u/24f7fd7b8b2d" target="_blank">
      <svg-icon iconClass="jian" class="jian" />
    </a>
  </div>
</template>


<script>
export default {};
</script>

<style scoped lang="scss">
#social {
  text-align: center;
  .img {
     20px !important;
  }
  a {
    margin-left: 10px;
  }
}
</style>

我们回过去再看main.vue
会发现在main.vue中有一个router-view,这个可以来渲染我们的对应的路由的页面
接下来我们来看index.vue

//index.vue

<template>
  <div id="consoleContainer">
    <MaodianAbout />
    <div style="height:80px;"></div>
    <MaodianWorks />
    <div style="height:80px;"></div>
    <MaodianBlog />
  </div>
</template>

<script>
import MaodianAbout from "./maodian/About";
import MaodianWorks from "./maodian/Works";
import MaodianBlog from "./maodian/Blog";
export default {
  data() {
    return {};
  },
  methods: {},
  created() {},
  mounted() {},
  components: {
    MaodianAbout,
    MaodianWorks,
    MaodianBlog
  }
};
</script>
<style lang="scss" scoped>
#consoleContainer {
}
</style>
//About.vue
<template>
  <div id="about">
    <bigTitle :configText="configText"></bigTitle>
    <el-row :gutter="20">
      <el-col :xs="24" :sm="8">
        <img class="img" src="@/assets/images/about.png" alt />
      </el-col>
      <el-col :xs="24" :sm="16">
        <div class="text_container">
          <div class="tag">
            <el-tag>lovecode</el-tag>
            <el-tag type="success">cook</el-tag>
            <el-tag type="info">sports</el-tag>
            <el-tag type="warning">harder</el-tag>
            <el-tag type="danger">optimism</el-tag>
          </div>
          <div class="info">
            <div style="background-color:#ecf5ff;padding:5px 0;">我是一个正宗的重庆崽儿,家住永川,现已24岁,积极谋生中~</div>
            <div
              style="background-color:#f0f9eb;padding:5px 0;"
            >性格呢?有时内向,有时外向,说话一般简单直接,比较好相处,做事认真负责~</div>
            <div
              style="background-color:#f4f4f5;padding:5px 0;"
            >平时喜欢看看电影,打打羽毛球,对炒菜也比较热爱,但尚未习得一手好厨艺,正在努力中~</div>
            <div
              style="background-color:#fdf6ec;padding:5px 0;"
            >毕业于重庆理工大(本科),本非计算机科班出身,但对代码有热情,于一年前投身与猿类大军~</div>
            <div style="background-color:#fef0f0;padding:5px 0;">很喜欢的一句话 no pain,no gain~</div>
          </div>
          <div class="social">
            <el-row>
              <el-col :xs="24" :sm="12">
                <span>简书:</span>
                <a
                  href="https://www.jianshu.com/u/24f7fd7b8b2d/"
                  target="_blank"
                >https://www.jianshu.com/u/24f7fd7b8b2d</a>
              </el-col>
              <el-col :xs="24" :sm="12">
                <span>github:</span>
                <a href="https://github.com/youyougu-me" target="_blank">github.com/youyougu-me</a>
              </el-col>
            </el-row>
          </div>
        </div>
      </el-col>
    </el-row>
  </div>
</template>

<script>
import bigTitle from "@/components/ModuleHeader";
export default {
  data() {
    return {
      configText: {
        sm: "INFORMATION",
        bg: "ABOUT ME"
      }
    };
  },
  methods: {},
  created() {},
  mounted() {},
  components: {
    bigTitle
  }
};
</script>
<style lang="scss" scoped>
#about {
  .img {
     100%;
    margin-bottom: 20px;
  }
  .text_container {
    .info {
      margin-top: 20px;
      div {
        color: $textColor;
        margin-top: 5px;
        letter-spacing: 1px;
        font-size: 14px;
        box-sizing: border-box;
      }
    }
    .social {
      margin-top: 20px;
      span {
        font-weight: bold;
        color: $textColor;
        margin-right: 5px;
        display: inline-block;
        margin-top: 10px;
      }
      a {
        text-decoration: underline;
        display: inline-block;
        margin-top: 10px;
      }
    }
  }

  //媒体查询
  @media screen and (max- $--screen-sm-min) {
    //小屏幕
    // .info {
    // 这个我把它写到了总的里面去
    //   padding: 0 5px;
    // }
  }
}
</style>
//Works.vue
<template>
  <div id="works">
    <bigTitle :configText="configText"></bigTitle>
    <!-- 经历时间线 -->
    <el-timeline>
      <el-timeline-item placement="top" color="#f17c67">
        <el-card>
          <template slot="header">
            <h1 class="title">重庆吉垚物业有限公司</h1>
            <span v-if="true" class="sub-title">2019.07——2020.06</span>
          </template>
          <p
            class="content"
          >吉垚是一家创业型公司,它也是将我引向互联网的灯塔.我是以实习生的身份步入公司.在那里有一群志同道合的伙伴,我们一起学习,相互扶持,合作开发了公司官网和物业后台管理系统.不仅技术得到了提升,也磨炼了自己的克服困难的意志,更收获了友谊.</p>
        </el-card>
      </el-timeline-item>
      <el-timeline-item placement="top" color="#f17c67">
        <el-card>
          <template slot="header">
            <h1 class="title">重庆长安汽车股份有限公司</h1>
            <span v-if="true" class="sub-title">2018.07——2019.06</span>
          </template>
          <p
            class="content"
          >毕业季,国企是我'理想'的企业.凭着自己可观的考试成绩和一些荣誉证书,我面试通过顺利进入了长安,在那里我负责的岗位是冲压车间设备管理.初入社会,只求一份工作,而未对自己的职业进行认真的思考.很感谢长安给我一年时间,让我明确自己的职业方向,决定投身于猿类大军.</p>
        </el-card>
      </el-timeline-item>
      <el-timeline-item placement="top" color="#f17c67">
        <el-card>
          <template slot="header">
            <h1 class="title">重庆理工大学</h1>
            <span v-if="true" class="sub-title">2014.09——2018.06</span>
          </template>
          <p
            class="content"
          >
          大学,回忆满满的一段时光,可能也是我人生中最悠闲最放松一段时光.在这里自己的眼界得到了提升,校园里丰富多彩的活动也使得自己的生活不再单调.
          </p>
        </el-card>
      </el-timeline-item>
    </el-timeline>
  </div>
</template>

<script>
import bigTitle from "@/components/ModuleHeader";
export default {
  data() {
    return {
      configText: {
        sm: "EXPERIENCE",
        bg: "MY EXPERIENCE"
      }
    };
  },
  methods: {},
  created() {},
  mounted() {},
  components: {
    bigTitle
  }
};
</script>
<style lang="scss" scoped>
#works {
  .el-card {
    .title {
      font-size: 16px;
    }

    .sub-title {
      font-size: 8px;
      margin-top: 5px;
      display: block;
    }
    .content {
      font-size: 14px;
      color: rgba(0, 0, 0, 0.65);
    }
  }

  //媒体查询
  //小屏幕
  @media screen and (max- $--screen-sm-min) {
  }
}
</style>
//blog.vue
<template>
  <div id="blog">
    <bigTitle :configText="configText"></bigTitle>
    <div class="myworks">
      <div class="workitem" v-for="(item,index) in content" :key="index">
        <h1 class="title">{{item.p0}}</h1>
        <div class="content">
          <div>{{item.p1}}</div>
          <div>{{item.p2}}</div>
          <div>
            作品链接:
            <a :href="item.p3">{{item.p3}}</a>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
import bigTitle from "@/components/ModuleHeader";
import {content} from "./conten";
export default {
  data() {
    return {
      configText: {
        sm: "PROJECTS",
        bg: "MY works"
      },
      content: content
    };
  },
  methods: {},
  created() {},
  mounted() {},
  components: {
    bigTitle
  }
};
</script>
<style lang="scss" scoped>
#blog {
  // height: 1000px;
  margin-bottom:100px;
  .myworks {
    .workitem {
      margin-top: 30px;
      .title {
        background-color: rgba(241, 124, 103, 0.3);
        padding: 10px 0;
        padding-left: 20px;
        font-weight: bold;
      }
      .content {
        margin-top: 10px;
        div {
          color: $textColor;
          margin-top: 5px;
          letter-spacing: 1px;
          font-size: 14px;
          box-sizing: border-box;
          border-bottom: 1px solid #ccc;
          line-height: 1.3;
          a {
            color: rosybrown;
          }
        }
      }
    }
  }

  //媒体查询
  @media screen and (max- $--screen-sm-min) {
    //小屏幕
  }
}
</style>
//ModuleHeader.vue
<!-- 每个内容模块的title -->

<template>
  <div id="heading">
    <el-row class="color-title">
      <el-col :span="24">
        <span>{{configText.sm}}</span>
      </el-col>
    </el-row>
    <el-row class="color-content">
      <el-col :span="24">
        <h2>{{configText.bg}}</h2>
      </el-col>
    </el-row>
  </div>
</template>

<script>
export default {
  data() {
    return {};
  },
  props: {
    configText: {
      default: () => {
        return {};
      }
    }
  }
};
</script>

<style scoped lang="scss">
#heading {
  border-left: 6px solid #e3872d;
  padding: 0.5em 0 0 1.5em;
  font-family: "Montserrat", sans-serif;
  margin-bottom: 30px;
   100%;
  box-sizing: border-box;

  span {
    font-size: 12px;
    text-transform: uppercase;
    font-weight: 400;
    letter-spacing: 5px;
  }

  h2 {
    font-weight: 500;
    font-size: 30px;
    letter-spacing: 3px;
    text-transform: uppercase;
    margin: 0;
  }
}
</style>
原文地址:https://www.cnblogs.com/smart-girl/p/13397124.html