现学现卖做前端(1) vue.js


引言

这是一个练手项目,想法是使用做一个前端,然后再将前端部署到服务器上,可以访问访问,一步一步学习心得技术框架。目前前端已做了一个简单的界面,并且可以访问。现在考虑加入数据库,实现前后端分离。
目前已经用到有:

  • Vue.js
  • ElementUI
  • MySql
  • Spring boot
  • AJAX
  • Json

效果

自己搭建的服务器经常打不开
github
在这里插入图片描述
先放个图,刚开始,自己也是参考这里边学边做,后面有时间还会改。


项目

  1. 新建项目
vue init webpack website
  1. 进入
cd website
  1. 安装依赖
npm install
  1. 安装element-ui
npm i element-ui -S

目录结构
目录结构


src

在这里插入图片描述
App.vue

<template>
  <div>
    <router-view></router-view>
  </div>
</template>

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

<style>
body {
  font-family: Arial, "STHeiti", Helvetica, sans-serif;
  font-size: 12px;
  margin: 0 auto;
  width: 100%;
  overflow-x: hidden;
  -webkit-overflow-x: hidden;
  -webkit-tap-highlight-color: transparent;
  background-image: linear-gradient(
    to right,
    rgba(174, 173, 243, 0.5) 0%,
    rgba(106, 204, 166, 0.5) 50%,
    rgba(209, 130, 106, 0.5) 100%
  );
}

/* .container {
  max-width: 80%;
  margin: 0 auto;
  padding: 0 10px;
  overflow-x: hidden;
  -webkit-overflow-x: hidden;
} */

/* 滚动条 */
.scrollbar {
  margin-left: 30px;
  float: left;
  height: 300px;
  width: 65px;
  background: #efefef;
  overflow-y: scroll;
  margin-bottom: 25px;
}
::-webkit-scrollbar-track {
  border-radius: 0px;
  background-color: #efefef;
}
::-webkit-scrollbar {
  width: 12px;
  background-color: #efefef;
}

::-webkit-scrollbar-thumb {
  border-radius: 10px;
  background: linear-gradient(
    to bottom,
    rgba(174, 173, 243, 0.5) 0%,
    rgba(106, 204, 166, 0.5) 50%,
    rgba(209, 130, 106, 0.5) 100%
  );
}
</style>

main.js

// The Vue build version to load with the `import` command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
import Vue from 'vue'
import App from './App'
import router from './router'
//引入element ui 2020年4月23日16:59:20
import ElementUI from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css';

Vue.config.productionTip = false

/* eslint-disable no-new */
Vue.use(ElementUI)

new Vue({
  el: '#app',
  router,
  components: { App },
  template: '<App/>'
})

components

在这里插入图片描述

header.vue
<!-- 头部公用 -->
<template>
  <div class>
    <div class="headBack">
      <el-row class="container">
        <el-col :span="12" :offset="5">
          <div class="headBox">
            <el-menu
              :default-active="activeIndex"
              class="el-menu-demo"
              mode="horizontal"
              @select="handleSelect"
              background-color="transparent"
              :router="true"
            >
              <el-menu-item class="el-menu-item" index="/Home">>>首页</el-menu-item>

              <el-menu-item index="2-1">>>音乐</el-menu-item>

              <el-menu-item index="3">>>关于</el-menu-item>
              <el-menu-item index="4">>>搜索</el-menu-item>
            </el-menu>
          </div>
        </el-col>
      </el-row>
    </div>

    <div class="jieshao">
      <p class="typer-dynamic">
        <span class="cut">
          I am&nbsp;
          <br />
          <span class="word" v-for="(letter,index) in words" :key="index">{{letter}}</span>
        </span>
        <!-- 模拟光标-->
        <!-- <span class="typer-cursor"></span> -->
      </p>
    </div>
    <div class="headImgBox" :style="{backgroundImage: 'url(static/img/header3.jpg)'}">
      <div class="bghtml">
        <iframe
          src="static/img/bjtx.html"
          frameborder="0"
          width="100%"
          scrolling="no"
          height="100%"
        ></iframe>
      </div>
      <div class="h-information">
        <div class="h-img">
          <a href="#/Aboutme">
            <img src="static/img/head.jpg" alt="头像" width="10%" />
          </a>
        </div>

        <h2 class="h-description">
          <span>今日事,今日毕</span>
        </h2>
      </div>
    </div>
  </div>
</template>
<script>
export default {
  name: "Header",
  data() {
    return {
      activeIndex: "1",
      activeIndex2: "1",
      words: [], //字母数组push,pop的载体
      str: "大橘为重", //str初始化
      letters: [], //str分解后的字母数组
      order: 1 //表示当前是第几句话
    };
  },

  methods: {
    //事件处理器
    handleSelect(key, keyPath) {
      console.log(key, keyPath);
    },
    //开始输入的效果动画
    begin() {
      this.letters = this.str.split("");
      for (var i = 0; i < this.letters.length; i++) {
        setTimeout(this.write(i), i * 100);
      }
    },
    //开始删除的效果动画
    back() {
      let L = this.letters.length;
      for (var i = 0; i < L; i++) {
        setTimeout(this.wipe(i), i * 50);
      }
    },
    //输入字母
    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);
        }
      };
    }
  },
  components: {
    //定义组件
  },
  watch: {
    // 如果路由有变化,会再次执行该方法
    order(old, newV) {
      if (this.order % 4 == 1) {
        this.str = "大橘为重";
      } else if (this.order % 4 == 2) {
        this.str = "looking for a job. ";
      } else if (this.order % 4 == 3) {
        this.str = "a front-end programmer.";
      } else {
        this.str = "coding the web...";
      }
    }
  },
  created() {
    //生命周期函数
    // console.log(this.$route);
  },
  mounted() {
    //页面元素加载完成
    this.begin();
  }
};
</script>

<style scope>
/*********头部导航栏********/
/*头部导航栏盒子*/
.headBack {
  width: 100%;
  background-image: linear-gradient(
    to right,
    rgba(174, 173, 243, 0.5) 0%,
    rgba(106, 204, 166, 0.5) 50%,
    rgba(209, 130, 106, 0.5) 100%
  );
  box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.12), 0 0 6px 0 rgba(0, 0, 0, 0.04);
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 10;
  /* z-index 让其中一个div浮在另一个div上面 ,越大代表越置前*/
}

.headBox .el-menu-demo {
  border-bottom: none !important;
}

.headBox .el-menu-demo li.el-menu-item {
  height: 40px;
  line-height: 40px;
  border-bottom: none !important;
}

.headBox ul li.el-menu-item {
  color: rgb(255, 255, 255);
}

/* 自我介绍 */
.jieshao {
  top: 200px;
  position: relative;
  text-align: center;
  font-size: 40px;
  opacity: 0.7;
  height: 50px;

  width: 50%;
  transform: translate(50%, 0);
  /* opacity 透明度 */
  z-index: 9;
}

.typer {
  box-sizing: border-box;
}
.typer .typer-content {
  font-weight: bold;
  display: flex;
  flex-direction: row;
  letter-spacing: 4px;
}
.typer-dynamic {
  position: relative;
}
.cut {
  color: #000000;
}
.typer-cursor {
  position: absolute;
  height: 100%;
  width: 3px;
  top: 0;

  background-color: #0f0000;
  animation: flash 1.5s linear infinite;
}
/*头部背景图*/
.headImgBox {
  width: 100%;
  height: 100%;
  position: absolute;
  top: 0;
  background-size: cover;
  background-position: center 50%;
  background-repeat: no-repeat;
  margin-bottom: 90px;
}
/* .h-information :hover {
  transform: translate(0, -2px);
} */
.h-information {
  text-align: center;
  width: 85%;
  margin: auto;
  height: 180px;
  position: relative;
  top: 550px;
  padding: 25px 0;
  font-size: 16px;
  opacity: 0.98;
  /* background: transparent; */
  /* background: rgb(224, 211, 211); */
  border-radius: 13px;
  z-index: 1;
  margin-bottom: 90px;
  animation: b 0.8s ease-out;
  -webkit-animation: b 0.8s ease-out;
}

@keyframes b {
  0% {
    -webkit-transform: translateY(50px);
    transform: translateY(50px);
  }
  80% {
    -webkit-transform: translateY(2px);
    transform: translateY(2px);
  }
  90% {
    -webkit-transform: translateY(-2px);
    transform: translateY(-2px);
  }
  to {
    -webkit-transform: translateY(0);
    transform: translateY(0);
  }
}

.h-information img {
  width: 100px;
  height: 100px;
  border-radius: 100%;
  transition: all 0.4s ease-in-out;
  -webkit-transition: all 0.4s ease-in-out;
  object-fit: cover;
}
.h-information img:hover {
  transform: rotate(360deg);
  -webkit-transform: rotate(360deg);
}

.bghtml {
  text-align: center;
  width: 50%;
  transform: translate(50%, 0);
  margin: auto;
  height: 200px;
  position: absolute;
  top: 530px;
  padding: 20px 0;
  font-size: 16px;
  opacity: 0.98;
  /* background: transparent; */
  /* background: rgb(231, 42, 42); */
  border-radius: 13px;
  z-index: 1;
  margin-bottom: 90px;
  
}
</style>

在这里插入图片描述

footer.vue
<!-- 底部公用 -->
<template>
  <div class="footBack"> 
    <div class="fcontainer">
      <p>
        博客已艰难运行
        <span v-html="longTime">{{longTime}}</span>
      </p>
      <p>
        文字
        <a href target="_blank">文字</a>.
        <a href target="_blank">文字</a>.
        <a href target="_blank">文字</a>.
        <a href target="_blank">文字</a>.
      </p>
      <p>
        © 2020
        <a href target="_blank">Vue</a> 
      </p>
    </div>
  </div>
</template>

<script>
export default {
  data() {
    //选项 / 数据
    return {
      longTime: ""
    };
  },
  methods: {
    //事件处理器
    runTime: function() {
      //运行倒计时
      var that = this;
      var oldTime = new Date("2020/04/24 00:00:00");
      var timer = setInterval(function() {
        var nowTime = new Date();
        var longTime = nowTime - oldTime;
        var days = parseInt(longTime / 1000 / 60 / 60 / 24, 10); //计算剩余的天数
        var hours = parseInt((longTime / 1000 / 60 / 60) % 24, 10); //计算剩余的小时
        var minutes = parseInt((longTime / 1000 / 60) % 60, 10); //计算剩余的分钟
        var seconds = parseInt((longTime / 1000) % 60, 10); //计算剩余的秒数
        that.longTime =
          days + "天" + hours + "小时" + minutes + "分" + seconds + "秒";
      }, 1000);
    }
  },
  components: {
    //定义组件
  },
  created() {
    //生命周期函数
    //替换底部图片
    var that = this;
    that.runTime();
  }
};
</script>

<style>
.footBack {
  line-height: 1.5;
  font-size: 12px;
  text-align: center;
  width: 100%;
}
.footBack .fcontainer{
      /* background-image: linear-gradient(
    to right,
    rgba(174, 173, 243, 0.5) 0%,
    rgba(106, 204, 166, 0.5) 50%,
    rgba(209, 130, 106, 0.5) 100%
  ); */
    width:100%;
    padding:15px 10px 10px 10px;
}
</style>

在这里插入图片描述

temAboutwebsite.vue
<!-- 关于本站 -->
<template>
  <div class="Aboutweb">
    <el-timeline>
      <el-timeline-item timestamp="2020年5月2日16:59:30" placement="top">
        <section class="Aboutweb-card">
          <h4>增加 Aboutme</h4>
          <p>大橘为重 提交于 20205216:59:30</p>
        </section>
      </el-timeline-item>
      <el-timeline-item timestamp="2020年5月2日16:59:25" placement="top">
        <section class="Aboutweb-card">
          <h4>增加 Home</h4>
          <p>大橘为重 提交于 20205216:59:25</p>
        </section>
      </el-timeline-item>
      <el-timeline-item timestamp="2020年5月2日16:59:08" placement="top">
        <section class="Aboutweb-card">
          <h4>建站</h4>
          <p>大橘为重 提交于 20205216:59:08</p>
        </section>
      </el-timeline-item>
    </el-timeline>
  </div>
</template>

<script>
export default {
  data() {
    //选项 / 数据
    return {};
  }
};
</script>

<style>
.Aboutweb {
  margin-top: 100px;
  /* position: relative; */
  width: 75%;
  margin-left: 13%;
  margin-bottom: 50px;
}

.Aboutweb-card {
  border: 1px dashed rgba(100, 166, 197, 0.7);
  background: transparent;
}
</style>
temAboutme.vue
<!-- 关于我 -->
<template>
  <div class="Aboutme">
    <p class="resume">我的简历</p>
    <p class="resume item">个人简况</p>
    <table>
      <tbody>
        <tr>
          <td>学 校:</td>
          <td>XX大学</td>
          <td>院 系:</td>
          <td>计算机与信息学院</td>
          <td rowspan="5">
            <img width="120" src="https://s2.ax1x.com/2019/11/04/KxQrp8.jpg" />
          </td>
        </tr>
        <tr>
          <td>专 业:</td>
          <td>计算机科学与技术</td>
          <td>电 话:</td>
          <td>151****2057</td>
        </tr>
        <tr>
          <td>学 历:</td>
          <td>研二在读</td>
          <td>现 居 地:</td>
          <td>南京市江宁区</td>
        </tr>
        <tr>
          <td>QQ/微信:</td>
          <td>123456789</td>
          <td>E - mail:</td>
          <td>123456789@qq.com</td>
        </tr>
        <tr>
          <td>Github:</td>
          <td>
            <a href="">https://githubb.com/123456xxx</a>
          </td>
          <td>个人网站:</td>
          <td>
            <a href="">https://xxx.fun/</a>
          </td>
        </tr>
      </tbody>
    </table>
    <p class="resume item">通信地址</p>
    <p class="resume address">
       XX大学XX校区XX西路8号 ,邮编:211111
    </p>
  </div>
</template>

<script>
export default {
  data() {
    //选项 / 数据
    return {};
  }
};
</script>

<style  >
.Aboutme {
  /* margin-top: 10px; */
  width: 70%;
  margin-left: 15%;
  margin-bottom: 100px;
  background: transparent;
  font-size: 18px;
  text-align: center;
  line-height: 1.5;
}
table {
  width: 100%;
  display: table;
  border-collapse: collapse;
  border-spacing: 0;
}
table,
th,
td {
  padding: 13px 13px;
  border: 1px solid rgba(108, 90, 189, 0.7);
}
td:hover {
  transform: translate(0, -1px);
}
.resume {
  font-family: "Franklin Gothic Medium", "Arial Narrow", Arial, sans-serif;
  font-size: 30px;
  font-weight: bold;
}
.item {
  font-size: 27px;
  text-align: left;
}
.address {
  font-weight:normal;
  text-align: left;
  font-size: 18px;
}
</style>

pages

Home.vue
<template>
  <div>
    <wbc-nav></wbc-nav>
    <div class="container home">
      <el-row :gutter="15">
        <el-col
          :sm="24"
          :md="15"
          :offset="0"
          style="transition:all .5s ease-out;margin-bottom:30px;"
        >
          <wbc-content class="content"></wbc-content>

          <br />
        </el-col>
        <el-col :sm="24" :md="9">
          <br />
          <br />
        </el-col>
      </el-row>
    </div>

    <wbc-footer></wbc-footer>
  </div>
</template>

<script>
import header from "../components/header.vue";
import footer from "../components/footer.vue";
// import temContent from "../components/temContent.vue";

export default {
  name: "Home",
  data() {
    return {
      msg: "home"
    };
  },
  components: {
    //定义组件
    "wbc-nav": header,
    "wbc-content": temContent,
    "wbc-footer": footer
  }
};
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
</style>

Aboutwebsite.vue
<!-- 关于本站 -->
<template>
  <div>
    <!-- <wbc-nav></wbc-nav> -->
    <div>
      <wbc-aboutweb></wbc-aboutweb>
    </div>
    <wbc-footer></wbc-footer>
  </div>
</template>

<script>
import header from "../components/header.vue";
import footer from "../components/footer.vue";
import aboutweb from "../components/temAboutwebsite.vue";

export default {
  name: "Aboutwebsite",
  data() {
    //选项 / 数据
    return {
      msg: "关于本站"
    };
  },
  components: {
    //定义组件
    "wbc-nav": header,
    "wbc-aboutweb": aboutweb,
    "wbc-footer": footer
  },
};
</script>

<style>
</style>

在这里插入图片描述

Aboutme.vue
<!-- 关于我 -->
<template>
  <div>
    <wbc-nav></wbc-nav>
    <div>
      <wbc-about></wbc-about>
    </div>
    <wbc-footer></wbc-footer>
  </div>
</template>

<script>
import header from "../components/header.vue";
import footer from "../components/footer.vue";
import temAbout from "../components/temAboutme.vue";

export default {
  name: "Aboutme",
  data() {
    //选项 / 数据
    return {
      msg: "关于我"
    };
  },
  components: {
    //定义组件
    "wbc-nav": header,

    "wbc-about": temAbout,
    "wbc-footer": footer
  },
  created() {
    //生命周期函数
  }
};
</script>

<style>
</style>

在这里插入图片描述


router

在这里插入图片描述

index.js
import Vue from 'vue'
import Router from 'vue-router'
 

Vue.use(Router)

export default new Router({
  routes: [
    {
      path: '/',
      name: 'Home',
      component: resolve => require(['../pages/Home.vue'], resolve),
      meta: {
        auth: true
      },
    }, //首页
    {
      path: '/Home',
      name: 'Home',
      component: resolve => require(['../pages/Home.vue'], resolve),
    }, //首页
    {
      path: '/Aboutme',
      name: 'Aboutme',
      component: resolve => require(['../pages/Aboutme.vue'], resolve),
      meta: {
        auth: true
      }
    }, //关于
    // {
    //   path: '/Music',
    //   name: 'Music',
    //   component: resolve => require(['../pages/Music.vue'], resolve),
    //   meta: {
    //     auth: true
    //   }
    // }, //音乐
    {
      path: '/Aboutwebsite',
      name: 'Aboutwebsite',
      component: resolve => require(['../pages/Aboutwebsite.vue'], resolve),
      meta: {
        auth: true
      }
    }, //本站
  ]
})

static

在这里插入图片描述
bjtx.html

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<style>
 body {
	background: transparent;

}
</style>


</head>
<body >
<canvas height="100%" width="100%" style="position: fixed; top: 0px; left: 0px; z-index: -1; opacity: 0.4;"  id="canvas"></canvas>
<script>
var canvas,
	ctx,
	width,
	height,
	size,
	lines,
	tick;

function line() {
	this.path = [];
	this.speed = rand(10, 20);
	this.count = randInt(10, 30);
	this.x = width / 2, +1;
	this.y = height / 2 + 1;
	this.target = {
		x: width / 2,
		y: height / 2
	};
	this.dist = 0;
	this.angle = 0;
	this.hue = tick / 5;
	this.life = 1;
	this.updateAngle();
	this.updateDist();
}

line.prototype.step = function(i) {
	this.x += Math.cos(this.angle) * this.speed;
	this.y += Math.sin(this.angle) * this.speed;

	this.updateDist();

	if (this.dist < this.speed) {
		this.x = this.target.x;
		this.y = this.target.y;
		this.changeTarget();
	}

	this.path.push({
		x: this.x,
		y: this.y
	});
	if (this.path.length > this.count) {
		this.path.shift();
	}

	this.life -= 0.001;

	if (this.life <= 0) {
		this.path = null;
		lines.splice(i, 1);
	}
};

line.prototype.updateDist = function() {
	var dx = this.target.x - this.x,
		dy = this.target.y - this.y;
	this.dist = Math.sqrt(dx * dx + dy * dy);
}

line.prototype.updateAngle = function() {
	var dx = this.target.x - this.x,
		dy = this.target.y - this.y;
	this.angle = Math.atan2(dy, dx);
}

line.prototype.changeTarget = function() {
	var randStart = randInt(0, 3);
	switch (randStart) {
		case 0: // up
			this.target.y = this.y - size;
			break;
		case 1: // right
			this.target.x = this.x + size;
			break;
		case 2: // down
			this.target.y = this.y + size;
			break;
		case 3: // left
			this.target.x = this.x - size;
	}
	this.updateAngle();
};

line.prototype.draw = function(i) {
	ctx.beginPath();
	var rando = rand(0, 10);
	for (var j = 0, length = this.path.length; j < length; j++) {
		ctx[(j === 0) ? 'moveTo' : 'lineTo'](this.path[j].x + rand(-rando, rando), this.path[j].y + rand(-rando, rando));
	}
	ctx.strokeStyle = 'hsla(' + rand(this.hue, this.hue + 30) + ', 80%, 55%, ' + (this.life / 3) + ')';
	ctx.lineWidth = rand(0.1, 2);
	ctx.stroke();
};

function rand(min, max) {
	return Math.random() * (max - min) + min;
}

function randInt(min, max) {
	return Math.floor(min + Math.random() * (max - min + 1));
};

function init() {
	canvas = document.getElementById('canvas');
	ctx = canvas.getContext('2d');
	size = 30;
	lines = [];
	reset();
	loop();
}

function reset() {
	width = Math.ceil(window.innerWidth / 2) * 2;
	height = Math.ceil(window.innerHeight / 2) * 2;
	tick = 0;

	lines.length = 0;
	canvas.width = width;
	canvas.height = height;
}

function create() {
	if (tick % 10 === 0) {
		lines.push(new line());
	}
}

function step() {
	var i = lines.length;
	while (i--) {
		lines[i].step(i);
	}
}

function clear() {
	ctx.globalCompositeOperation = 'destination-out';
	ctx.fillStyle = 'hsla(0, 0%, 0%, 0.1';
	ctx.fillRect(0, 0, width, height);
	ctx.globalCompositeOperation = 'lighter';
}

function draw() {
	ctx.save();
	ctx.translate(width / 2, height / 2);
	ctx.rotate(tick * 0.001);
	var scale = 0.8 + Math.cos(tick * 0.02) * 0.2;
	ctx.scale(scale, scale);
	ctx.translate(-width / 2, -height / 2);
	var i = lines.length;
	while (i--) {
		lines[i].draw(i);
	}
	ctx.restore();
}

function loop() {
	requestAnimationFrame(loop);
	create();
	step();
	clear();
	draw();
	tick++;
}

function onresize() {
	reset();
}

window.addEventListener('resize', onresize);

init();

</script>

</body>
</html>

回到顶部

增加 <el -backtop > 在 < div> 内。

<template>
  <div class="Data">
    <el-backtop> </el-backtop>
    <p class="bookdata">书籍数据展示</p>
      
  </div>
</template>

参考链接

vue.js搭建个人博客
模拟生成打字(支持无数段)

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值