文章目录
引言
这是一个练手项目,想法是使用做一个前端,然后再将前端部署到服务器上,可以访问访问,一步一步学习心得技术框架。目前前端已做了一个简单的界面,并且可以访问。现在考虑加入数据库,实现前后端分离。
目前已经用到有:
- Vue.js
- ElementUI
- MySql
- Spring boot
- AJAX
- Json
效果
自己搭建的服务器经常打不开
github
先放个图,刚开始,自己也是参考这里边学边做,后面有时间还会改。
项目
- 新建项目
vue init webpack website
- 进入
cd website
- 安装依赖
npm install
- 安装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
<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>大橘为重 提交于 2020年5月2日16: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>大橘为重 提交于 2020年5月2日16: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>大橘为重 提交于 2020年5月2日16: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>