个人博客开发踩坑记录(待整理)

1,742 阅读13分钟

2019-09-23


用Vue CLI3搭建了的项目的基本结构,将代码推送到远程,遇到的问题主要有两个

1。vue中import引入模块路径中@符号是什么意思?

image

@ 等价于 /src 这个目录,避免写麻烦又易错的相对路径

2。使用sass语法需要安装sass-loader、node-sass

image
sass-loader是css预处理器,可以在CLI创建项目的时候安装,也可以项目创建完成后手动安装 参考链接

9-24


使用二级路由完成导航栏的开发

image
主要遇到问题有

1。导航栏组件跟浏览器的上、左右间留有空白

image
解决办法是在App.vue设置body的内边距和外边距为0

body{
	margin: 0;
	padding: 0;
}

2.如何适配手机屏幕 参考链接

3。css如何垂直居中

方法不唯一,这里使用flex布局,加上align-items: center; 属性

水平居中使用了justify-content: center; 属性

display: flex;
align-items: center;
justify-content: center;

这段代码可以让元素水平和垂直方向都居中

image

9-25


遇到的问题主要有

1。引入轮播图片

在模板中这样是没问题的:

<img src="../../imgs/c3.png" />

但是我把地址提取出来,放到 data 里,就引用不到了:

<img :src="img3" >
export default {
data() {
	return {
              img3: '../../imgs/c3.png'
            }
     }
}

解决办法

1)写在模板不出错,是因为你已经有模板的图片解析器了,在JS中需要import

2)放在模版里是会被 webpack 打包出来,所以可以。 而在 js 里写图片路径其实只是字符串 webpack 不会处理 如果想这么做 你可以把图片放在最外层的 static 文件夹 或使用 import 、require 引入

import img3 from '../../imgs/c3.png'

const img3=require('../../imgs/c3.png')

在data里引用变量

export default {
data() {
	return {
              img3:img3
            }
     }
}

在模板里直接引入路径打包编辑出来是这样的

image
而在data中没有经过import或require引入直接写路径的,打包出来是这样的

image
参考链接

2。项目的友情链接这里遇到两个问题

image
1)自动换行

数字或者英文超出规定区域不会自动换行,而中文会。 若要实现英文或数据也会自动换行,则span标签需要添加属性word-wrap:break-word; 中文想实现不自动换行则添加属性white-space: nowrap;

2) 使用float浮动时,当元素一行排不下了会自动排到下一行,但并不会撑大容器的高度,这里的解决办法是额外标签清除浮动

<div style="clear:both;"></div>

参考链接

9-26


我说为什么在App.vue的body标签的不起作用呢,原来是用scoped指定了只在当前组件有效

image

运行页面没有问题,但控件台却有报错

image
对应代码

image
解决后代码

image
把key改成唯一值就可以了

2。组件传参 segmentfault.com/a/119000001…

3。取消文本输入框边框和鼠标点入后默认的颜色

outline: none;
border: none;

今日总结

今天基本在宿舍写了一天的代码,初步完成了所有文章和留言页面的布局和样式。由于对代码掌握的还不熟练,基础不够扎实。遇到的很多的问题当解决之后就发现挺基础的。App.vue并不是只能放<router-view></router-view>,之前就是错误的认为是只能通过该标签访问路径为/的路由,所示建了一个Nav.vue作为一级路由,导航栏为一级路由,通过导航跳转的页面就都是二级路由了。然后今天看了之前的学习代码,导航条可以放在App.vue,即Nav.vue的代码放到了App.vue,再修改一下路由表,原来的二级路由变成一级路由。删除掉Nav.vue。

接着在App.vue设置body改变背景色,没有生效,之前还好好的。还是哪以前的练习代码来测试,发现没问题,经多次检查发现是<style>标签的scoped属性,scoped属性的作用是样式只在当前组件生效,之前习惯了但凡是组件都加上这个,这里去掉这个属性就好了。

右侧的组件“关注我”模块,之前只准备了4个栏位,采用了flex布局,今天想到今后可能要放更多图标,所示就用网络布局,设计了8个栏位,两行四列,如下代码

display: grid;
grid-template-columns: repeat(4, 25%);
grid-template-rows:90px 90px;

四个列宽就占25%,两个行高都是90px。

justify-content和align-items一样只在flex布局时生效,文本水平对齐的话用text-align,垂直居中的话可以设置行高line-height来实现。

linkActiveClass来指定路由导航激活状态的class名字,<router-view></router-view>上不需要添加这个class名

使用变量来引用属性值还挺方便的,当这个值多次需要用到且不易手写的时候。

$rgbcolor:rgb(231, 72, 81) !global 

border-radius可以有一到四个值,一个值是作用在四个角,两个值时:第一个值是左上角,第二个值是右上角。三个半径值分别表示:左上角 右上角和左下角 右下角。 四个半径值分别表示:左上角 右上角 右下角 左下角 (顺时针);

border-radius:60px/40px;

注:这两个半径值分别代表是水平/垂直方向的半径

image

input标签和textarea输入框可以不要边框,属性是border:none; 鼠标点击进入时,可以不要边框默认产生有点蓝的颜色那么设置

border: none;

也可以在input:focus{}里指定border为其它值。设置其内边距光标会移动

min-width属性和width=100%的配合使用、使用element-ui的上传图片组件来上传头像等也费了一番周折

今天就到这吧。夜深人静,晚安!

9-27


路由跳转回到页面顶部,官网

scrollBehavior (to, from, savedPosition) {
	  return { x: 0, y: 0 }
	}

鼠标悬停变成小手cursor:pointer;

鼠标悬停显示图片,css实现思路是图片外层容器是相对定位,图片是绝对定位且display:none;当鼠标放上去使用伪类:hover,display变成block

然而element-ui提供了更好的实现方案,就是用Tooltip文字提示组件

用具名 slot 分发content,替代tooltip中的content属性。

<el-tooltip placement="top">
  <div slot="content">多行信息<br/>第二行信息</div>
  <el-button>Top center</el-button>
</el-tooltip>

引入scss文件

@import "@/components/scss/detail.scss"

路由传参

goDetail(val) {
this.$router.push({
name:'/Detail',
params:{
article:val
}
})
}

取参

article:this.$route.params.article

今日总结

完成了文章详情页面的基本布局和样式

image
将昨天写的留言功能封装成一个组件,这样在文章的评论就可以直接复用,无需重复造轮子,文章详情是通过路由携带数据跳转进入的,有个问题是,当刷新该页面的时页面没有数据,控件台报错,这也在意料之中,这里的设计思路是当第一次通过路由跳转进入时,将数据保存起来(后面是否需要vuex),当刷新页面的时候,再将保存的数据取出渲染到页面,如果保存的数据不存在了,再发起网络请求调用后台接口。这样的好处是减少网络请求,减少服务器开销。

9-28


innerHTML改变页面div元素 参考,打赏功能用了这种方式

今日总结

打赏功能用element ui的弹框组件实现点击按钮弹出,再使用innerHTML来切换支付宝和微信的二维码,开始以为是用路由来实现的,结果以失败告终。到后面发现有更好的实现方式,就是使用绑定class来实现,在data中设置一个Boolear变量,通过点击按钮来改变布尔值,在:class中使用三元表达式来选择要渲染的样式,按钮的选中状态和未选中状态样式的切换就是通过这样来达到预期效果的。而通过display:none;就可以实现内容的显隐状态,还不会占用原来的位置。这样就能实现同一块地方,点击不同的按钮,显示的内容就不一样。注册登录间的切换就是这么来实现的。

登录注册用到了element ui的表单组件,表单组件里的表单校验也费了一波周折,空格输入也能通过效验,还好组件里提供了正则表达式,经过多次的尝最终也搞定了。评论组件再度封装,把用户输入要提交的评论内容(之前只封装了评论展现的模块)和注册登录也封装到评论组件里,这样留言页面和文章详情页面都可以直接引用,至此越发觉得vue的组件开发这一点真是太棒了,提高性能暂且不说,主要是方便偷懒,能复制粘贴的就不要自己写,能直接引用的就绝不复制粘贴,我相信这是绝大多数开发人员的内心诉求,哈哈哈哈

image

image

9-29


今日总结

因为大部分功能都有了,今基本没有添加什么额外的功能,主要就是处理一些细节。使用阿里云的图标库给页面添加图标,添加了限制评论输入框字数上限功能,这里还是被卡了一会儿,结合输入框元素(input或textarea)自带的maxLength属性和vue的watch来监听属性值变化,当然实现方式很多,我使用了自己觉得最简单的一种,灵感来源于下面这段代码

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>Examples</title>
<meta name="description" content="">
<meta name="keywords" content="">
<link href="" rel="stylesheet">
<script src="https://cdn.bootcss.com/vue/2.4.2/vue.min.js"></script>
</head>
<body>
    <div id="app">
        <input type="text" v-model="items.text" ref="count"/>
        <div  v-html="number"></div>
    </div>
    <script>
        new Vue({
            el: '#app',
            data: {
                number: '100',
                items: {
                    text:'',
                },
            },
            watch:{   //watch()监听某个值(双向绑定)的变化,从而达到change事件监听的效果
                items:{
                    handler:function(){
                        var _this = this;
                        var _sum = 100; //字体限制为100个
                        _this.$refs.count.setAttribute("maxlength",_sum);
                        _this.number= _sum- _this.$refs.count.value.length;
                    },
                    deep:true
                }
            }
        })
    </script>
</body>
</html>

 - handle就是你watch中需要具体执行的方法
 - deep:就是你需要监听的数据的深度,一般用来监听对象中某个属性的变化
 - immediate:在选项参数中指定 immediate: true 将立即以表达式的当前值触发回调

不过我觉得我的更简单,代码更少,如下

<template>
<div class="comment-content">
<textarea class="" placeholder="既然来了,就说几句吧" v-model="textarea" :maxlength="maxLength"></textarea>
<div class="len">您还可以输入{{len}}个字</div>
</div>
</template>
<script>
export default {
		data() {
			return {
				textarea:'',
				maxLength:150,
				len:150
			}
		},
		watch:{
			textarea(){
					  this.len=this.maxLength - this.textarea.length
			}
		}
	}
</script>

实现的效果如下

image
当然,这里其它代码、样式都没有贴出来

其次就是解决了之前留下来的问题:从文章列表通过路由携带数据跳转到文章详细页面可以正常渲染数据,但是当强制刷新浏览器的时候,数据消失,控制台报属性未定义的错误。在解决这个问题的过程中遇到的问题首先是对localStorage的使用并熟练,毕竟自己第一次用,之前倒是看到别人用过,下面就是我目前了解到的

对浏览器来说,使用 Web Storage 存储键值对比存储 Cookie 方式更直观,而且容量更大,它包含两种:localStorage 和 sessionStorage。 注意:sessionStorage 和 localStorage 的用法基本一致,引用类型的值要转换成JSON(JSON.stringify()),相应的取出来需要解析JSON.parse(),这里就只列举localStorage

保存

//对象
const info = { name: 'hou', age: 24, id: '001' };
//字符串
const str="haha";
localStorage.setItem('hou', JSON.stringify(info));
localStorage.setItem('zheng', str);

获取

var data1 = JSON.parse(localStorage.getItem('hou'));
var data2 = localStorage.getItem('zheng');

删除

/删除某个
localStorage.removeItem('hou');
//删除所有
localStorage.clear();

浏览器中查看

image

localStorage有效期是永久的。一般的浏览器能存储的是5MB左右。sessionStorage api与localStorage相同。 sessionStorage默认的有效期是浏览器的会话时间(也就是说标签页关闭后就消失了)。 localStorage作用域是协议、主机名、端口。(理论上,不人为的删除,一直存在设备中) sessionStorage作用域是窗口、协议、主机名、端口。

知道了这些知识点后,你的问题就很好解决了。 localStorage是window上的。所以不需要写this.localStorage,vue中如果写this,是指vue实例。会报错

参考

2)localStorage的使用问题解决了,那么接下来要怎么做呢,其实实现思路挺简单的,只是我一开始没有想到而已 在methods中定义一个方法

methods{{
setArticleData() {
var is = this.$route.params.article === undefined
if (is) {
console.log(is+'以后走的if是这里')
var d=JSON.parse(localStorage.getItem('data'))
console.log(d)
this.article = d
} else {
console.log(is+'第一次路由进来走的else是这里')
this.article = this.$route.params.article
localStorage.setItem('data',JSON.stringify(this.$route.params.article))
	}
}			
}

放入到mounted()或created(),这两个是vue的生命周期函数,vue实例被创建时就会自动执行

created() {
this.setArticleData();
}

这段代码应该很好理解,不需要再做过多的解释,一切尽在代码中

9-30


第二次犯同样的错误,这里再简单总结一下,在vue文件的模板中要想成功加载出图片,有三种方式可以实现。

第一种就是把图片放到public目录下(vue-cli2是在static目录),这个目录下的文件会原封不动的复制到最终的打包目录下。在模板中src可以直接引用。

第二种就是先通过require或import图片(在script标签里在export default外),接着还要在data里面定义变量接收,最后在模板里的src绑定src这个变量

第三种就是你直接在模板里面src直接引用网络图片 参考链接

今日总结

上午的时候想要把项目的element ui由原来的全部引入改成按需引入的,结果遇到各种各样的问题,最终以失败告终。以及去了解了目前基于vue的移动ui框架,结合自己这个项目的需求及该框架的流行程度、组件数量、开发文档是否友好、框架最后更新时间等,最终选择了Vant这个框架,用来制作该项目的移动端样式。

下午主要就是写首页在移动端的样式,用的是媒体查询,为了方便把所有的vue文件pc端的style提取成一个单独的scss文件,移动端的style也写在另一个单独的scss。首页就用了Vant框架的Popup组件,用来实现侧方导航栏。

image
明天再优化

10-1


router-link标签没有to属性控件台报错

image
图片为什么不可以使用margin:0 auto;来水平剧中吗?

因为img标签属于inline-block元素,翻译叫行内块元素,而margin:0 auto只对block元素起作用,叫块元素或块级元素。还有一个常用的块元素是inline,叫行内元素、内联元素、内嵌元素等。inline元素的由内容撑开元素,决定元素大小,宽高属性皆不可以设置,左右内边距单独设置可以起作用,但上下内边距,上下左右外边距单独设置不起作用,除非行内元素有内容,或者至少设置了左右内边距中的一属性且属性值不为0

今日总结

今天国庆节,我写了一天的代码以庆祝我新中国成立70周年。使用Vant的组件对移动端的登录注册弹框重新设计,以更好的适配手机屏幕,同样是使用Vant组件添加了下拉刷新的动画及首页的轮播图,以提高用户体验

image

10-2

今日总结

今天在pc端页面的左上角添加了网站的名字“夜幕”,其实是某网站生成的png图片,在移动端不可见,点击该图片所有位置会切换网站的背景色,切换的原理是通过加载App.vue页面不同的样式,因为其它路由跳转的页面都是渲染在App.vue的<router-view></router-view>, App.vue页面的最外层容器绑定class,通过修改一个布尔变量isNight的值来加载不同的class,再给字体图片加上点击事件,所触发的函数执行的操作就是修改这个布尔变量。

但是这里遇到了一个问题,在Comment.vue组件里给用户输入评论的文本输入框有自己默认的背景色(可能textarea标签属性inline-block元素的的原因),需要单独修改,这时候就需要通过路由传参和组件传递数据来将这个布尔变量传递过去,再根据这个变量去判断需要加载的class,道理同App.vue那里一样。首先是将App.vue的isNight变量通过路由携参跳转到Home页面,Home页面再将接收数据的数据传递给Article组件(文章列表),当通过点击文章列表的子项时,再通过路由携参跳转到文章详情页面Detail页面,Detail页面再将接收的isNight这个变量传递给Comment组件,Comment组件接收到这个变量再进行判断就好了。嗯,就是这样。但是当在文章详情页面或者留言页面点击切换背景色的时候文本输入框并没有变色,还是保持原来的颜色,原因是App.vue改变的isNight变量值并没有传递过来,需要先到首页再重新打开页面才会变色,所以我这里不管你在哪里点击切换背景色,都会自动跳转到首页。目前还没有更好的解决办法,暂且这样吧。

10-3

今日总结

手机端也添加了切换背景色的功能,以及给侧边弹框添加了图标,文章列表展现的文章内容仅截取一部分展现,加了边框阴影效果。将根据屏幕大小进行媒体查询的变量数值提取出来,放到一个var.scss文件中,然后每个用这个变量的地方都引入这个文件。本来想弄个配置成全局变量的,就不需要每次都引入这个文件了,但感觉有点麻烦,鉴于本项目也没有多少文件,干脆就放弃了。

10-12

由于网页初次打开速度慢,同时单面应用对SEO也不够友好。所以开始用nuxt.js对项目进行改造,由客户端渲染改成服务端渲染。项目迁移到nuxt.js的过程中也遇到了许多的问题。

1)开发工具放弃HbuilderX,改用WebStorm,原因是感觉WebStorm对代码提示比较友好。操作上跟IntelliJ IDEA也差不多。在WebStorm中这样引用图片编译器报错,虽然并不影响运行

image

10-13

npm install一直报错,主要原因可能就是node-sass安装出错,只能尝试着安装淘宝镜像将依赖一个个下载下来,成功解决

安装淘宝镜像

npm install -g cnpm --registry=https://registry.npm.taobao.org 

使用淘宝镜像安装node-sass

cnpm install node-sass --save

3)nuxt路由传参可以

<nuxt-link :to="{name:'detail',params:{article:item,isNight:isNight}}" ></nuxt-line>

4)路由激活类

nuxt.config.js

 router: {
    linkExactActiveClass: 'exact-active-link'
  },

default.js

.exact-active-link{
    background-color: rgb(255, 251, 240);
    border-top: 5px solid rgb(247, 120, 37);
}

在SSR中,created生命周期在服务端执行,node环境中没有localStorage所以会报错,将需要使用localStorage的代码放到浏览器使用的生命周期(mounted)中。

6)使用第三方框架

6.1) 通过 npm 安装

npm i vant -S

6.2)在plugins目录下新建文件

image
6.3)在nuxt.config.js中配置

plugins: [
    // '@/plugins/element-ui'
    {
      src: '~plugins/element-ui',
      ssr: true,
    },
    {
      src: '~plugins/vant',
      ssr: true,
    }
  ],

image

10-14

1) 要在js里调用路由参数需要使用this

image
2)Linux安装cnpm镜像

npm install -g cnpm --registry=https://registry.npm.taobao.org 

创建软连接方可全局访问

ln -s /root/node-v10.14.2-linux-x64/bin/cnpm /usr/local/bin/

3)组件export default代码抽离

about.js

const img = require('../imgs/c5.png')

export default {
  name: "about",
  data() {
    return {
      msg: "你好呀Hello world",
      img:img
    }
  }
};

about.vue

<script>
  import about from "../assets/js/about";
  export default {
      ...about
  }
</script>

4)探究publicPath:process.env.BASE_URL的使用

image

export default {
	data() {
		return {
			publicPath:process.env.BASE_URL
		}
	}
}
<img :src="`${publicPath}favicon.ico`" alt="">
<img :src="this.publicPath+'favicon.ico'" alt="">

5)vant不起作用

image
加入这行代码就可以了

import 'vant/lib/index.css';

image
6)vant的侧方弹框背景色要使用行内样式设置才生效 7)夜间背景色要放在指定的位置才生效,放最外层不起作用
image
8)背景切换存在问题 点击两次切换按钮再次进入文章详情输入框颜色没有切换 9)v-show 这里v-if不行,只能v-show
image

今日总结

改造并优化适配手机端的代码。用SQLyog连接远程数据库建了11张mysql数据库表,

image
t_admin是管理员表,用于后台管理员登录使用。t_article是文章表,t_attention存储站长的联系方式及写作平台,t_carousel存储pc端和手机端的轮播图,t_comment存储文章评论,t_icon存默认头像,用户注册时,当用户不上传头像时,随机给用户添加默认头像。t_like是存储文章的点赞数据:谁点赞了哪篇文章。t_link存储友情链接,t_message存储用户留言,t_user存储已经注册的用户数据,t_web存储网站的公共信息,比如背景图片,打赏二维码,网站备案号等。这些表肯是还不够的,后面需要时再建。

10-15

1)mybatis-generator不会由表生成代码,如果该表没有主键的话。 2)IntelliJ IDEA快捷键Ctrl+Alt+h可打开窗口开到该方法被调用的地方。Alt+s可以打开视图看到该类里的所有方法列表,方便快速找到该方法。Alt+Home展开导航目录。Ctrl+Alt+T创建测试类。Ctrl+Alt+m展开Maven。一个暑假没用IntelliJ IDEA写代码了,快捷键都忘了很多了。

今日总结

着手搭建了开发环境及项目结构,使用IntelliJ IDEA创建的SpringBoot项目、操作数据库用MyBatis,用swagger自动生成接口文档,用mybatis-generator由表生成部分代码,配置了跨域,除了评论其它网站展示的信息所要的接口都大致完成,交互方面如评论留言点赞上传图片等这些功能接口还没有写,登录接口差不多了,注册写了部分,发送验证码这块还没来得及写。

10-16

10-17

10-18

1)res不能重复

image
2)子组件向父组件传递通过

_that.$emit('func', false)

父组件通过这样接收并执行

<Register @func="getMsgFormSon"></Register>

getMsgFormSon是父组件中的方法,这里不需要加()及参数

3)父组件调用子组件的方法

<button @close="close">
<login ref="login"/>
</button>
close() {
  this.$refs.login.resetForm('ruleForm2');                
  }

resetForm()是子组件中的方法,'ruleForm2'作为参数传递过去

4)向数组开头添加数据通过unshift()

array_object.unshift( newelement1, newelement2, ... )

向数组尾部追加是通过push()

array_object.push( newelement1, newelement2, ... )

5)向localStorage中追加对象数据可以先取出解析得到数组,再往里追加数据,接着字符串化重新设置就可以了

var art = JSON.parse(localStorage.getItem('data'))
 art.comments.unshift(res.data.data)
localStorage.setItem('data', JSON.stringify(art))

10-19

1)加载首页的时候已经将每篇文章的详细信息通过后台接口传递回来了,进入文章详情页面是通过路由将文章的详细信息带过去,然后页面直接渲染出来,不需要再次发起网络请求后台数据。然而这也给数据的更新及传递带来了不便。比如给文章点赞、添加评论时,点赞、评论数量及评论信息并没有及时刷新到当前页面上,还是显示原来的数据,你需要切换到其他页面再进来才会刷新出最新数据,添加评论时就是这么做的

当前页面跳转到/refresh页面,该页面可以是空白页面

   this.$router.replace({
                    path: '/refresh',
                    query: {
                        t: Date.now()
                    }
                })

/refresh页面再跳转回上一个页面

    beforeRouteEnter(to, from, next) {
            next(vm => {
                vm.$router.replace(from.path)
            })
        }

这样就实现了页面刷新,当然这中间有一小段跳转而出现的空白页面,但这是目前能想到且能实现出来的最佳方案

2)

image
评论或者留言数量是通过父组件单独传递过来的。组件封装可以做到代码复用,详情页和留言页面复用了Comment这个组件,但因为传递的数据及操作不一样,也给开发带来了一些麻烦。留言页面可以通过给Comment组件传递一个包含所有留言的Array数组,然后通过数组.length可以统计出留言数量,但是在详情页却报错

Cannot read property 'length' of undefined

至于什么原因,目前我还不清楚,因此暂且只能通过父组件给子组件传参的方式来解决这个问题,在详情页取到数组长度传递到Comment组件,Comment通过props接收,props中的属性可以不指定类型 props: {num: ''},有时候指定了虽然页面可以正常展示但是控件台一直报错,尝试了几种类型都还是报错,也不知道为啥

Invalid prop: type check failed for prop "num". Expected Number with value 0, got String with value "".

3)提交评论和留言调用的接口都不一样,但详情页和留言页面都同时用了Comment这个组件,怎么做到点击同一按钮调用不同的接口呢?我这里暂时无解,我想到了点击不同的按钮来触发不同的点击事件从而实现调用不同的接口

 <el-button class="say" type="danger" @click="subMsg"
 v-show="aId===undefined">畅所欲言</el-button>
 <el-button class="say" type="danger" @click="subCom" v-show="aId!==undefined">畅所欲言</el-button>

通过加载Comment组件的页面的aId(文章id)是否为undefined来显示隐藏对应按钮,是undefined就是留言页面,不是undefined就是文章详情页面,再结合v-show指令可以实现需求 4)文章评论和留言都有这样一个需要:未登录用户都在每条评论或留言显示回复按钮,登录用户如果评论/留言是用户自己的,则只显示删除按钮,自己不能回复自己,若评论/留言不是自己的则只显示回复按钮。

    <div class="reply">
              <span v-show="item.aId!==undefined&myinfo.userId===item.uId" @click="removeCom(item.cId)">删除</span>
              <span v-show="item.aId===undefined&myinfo.userId===item.uId" @click="remove(item.mId)">删除</span>
              <span v-show="item.aId!==undefined&myinfo.userId!==item.uId" @click="reply()">回复</span>
              <span v-show="item.mId!==undefined&myinfo.userId!==item.uId" @click="reply()">回复</span>
            </div>

5)删除评论调完接口去到令一个页面再回来最新数据也没有刷新出来,看了一下后台及数据库,确定操作成功了呀,但是页面上还是显示着已经删除掉的数据,为啥呢?原因是遍历文章评论及显示的是在Comment组件实现,而数据却是通过详情页面传递过来的,当离开详情页面再进来的时候,它是从localStorage中取到数据的,第一次进入详情页面的时候已经存进去了。为啥要把数据存进localStorage呢,因为路由跳转进来是通过如下这样方式跳转的

:to="{name:'detail',params:{article:item}}

这种路由携参跳转页面的方式不会把携带的数据显示在地址栏上,缺点是当强制刷新页面即F5的时候,页面数据就没了,为了解决这个问题,不改变路由跳转携参方式的情况下,我想到了把数据存储到localStorage当中,当通过路由进入详情页面的时候,页面取路由带过来的数据,这么说不准确,因为进入其它页面再进入取的还是localStorage的数据,应该说是当路由携带的数据满足条件时,取路由带的数据,不符合条件时则从localStorage取数据,看下面这行代码

                var is = this.$route.params.article === undefined

当满足条件时

                    this.article = this.$route.params.article;

当不满足条件时,如F5,页面从localStorage中取数据

                    let d = JSON.parse(localStorage.getItem('data'))

这样就很好解释为什么删除评论成功立即跳转到/refresh再进来为啥最新数据没有显示到页面上了,因为它取的依然是localStorage的数据。既然知道这样,我们就在执行页面刷新前修改localStorage中的数据

var art = JSON.parse(localStorage.getItem('data'))
art.comments.forEach((item, index) => {
if (item.cId === id) {
art.comments.splice(index, 1)
localStorage.setItem('data', JSON.stringify(art))
}
})

10-20

今天对手机端的登录注册弹框进行了改造,为了更好的调用接口、参数传递及用户体验,虽然UI不怎么好看,后面有时间再慢慢优化吧,但是主要功能都有。因为手机端用的是Vant框架,所以注册、登录、用户信息、修改密码等这些弹框及里面的表单都需要重新写一套,表单进行了前后端的双重验证

10-21

进行手机端的修改密码前端页面开发并调用接口,封装在一个名为NewPass的组件当中,在Comment组件当中使用,修改密码的入口是在Login组件上,当点击忘记密码按钮Login组件将数据传递到Comment组件,Comment组件再次数据传递到NewPass组件,这样来实现登录弹框消失修改密码弹框出现的需求,当修改密码请求成功弹框自动隐藏接着登录弹框自动弹出,这里使用了setTimeout来实现延迟弹框关闭,毕竟希望两个弹框的切换不太突兀,同时也是为了等待提示框的消失,操作成功或失败都会有提示,pc端用的是element ui提供的组件,手机端用的是vant的提示组件,pc端和手机端修改密码组件里点击的是不同的按钮,调用的也是不同的函数,但这两个函数都同时调用了一个封装了axios请求接口的方法,后台返回提示语,前端只负责展示,前端通过设置一个布尔变量就可以实现使用的是elment ui还是vant提供提示组件

10-23

select count(*) from t_comment where to_days(c_time) = to_days(now()) and u_id=1 and a_id=1;

2)springboot定时任务


@Component
@Configuration      //1.主要用于标记配置类,兼备Component的效果。
@EnableScheduling   // 2.开启定时任务
public class SaticScheduleTask {
    //3.添加定时任务
    @Scheduled(cron = "0 0-10 9 * * ?")
    //或直接指定时间间隔,例如:5秒
    //@Scheduled(fixedRate=5000)
    private void configureTasks() {
        System.err.println("执行静态定时任务时间: " + LocalDateTime.now());
    }
}

10-25

1)js ==与===区别(两个等号与三个等号) 2)过滤

10-27

在布局vue文件中将图片设置为背景,body中设置不起作用,如下设置可以达到效果,放大缩小浏览器都不会改变背景图

 .container{
    position: absolute;
    height: 100%;
    width: 100%;
    top:0;
    left: 0;
    overflow-y: auto;
    background-color: red;//背景为白
    background-image: url("../assets/imgs/banner1.jpg") ;
    background-repeat:no-repeat;
    background-size:cover;
  }

10-29

开始着手后台管理系统的开发 1)div高度占满整个屏幕

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>div高度占满整个屏幕</title>
    <style type="text/css">
     .main {
         padding: 0;
         margin: 0;
         position: absolute;
         left: 0;
         top: 0;
         bottom: 0;
         right: 0;
         background: red;
     }
    </style>
</head>
 
<div class="main">
    
</div>
</body>
</html>

或者

     overflow: hidden;
        position: fixed;
        width: 100%;
        height: 100%;
        background-size: cover;
        background-image: url("../public/images/bg.jpg");

10-30

转换时间戳

  filters:{
            changeTime(value) {
                var date = new Date(value);
                var y = date.getFullYear();
                var m = date.getMonth() + 1;
                m = m < 10 ? ('0' + m) : m;
                var d = date.getDate();
                d = d < 10 ? ('0' + d) : d;
                var h = date.getHours();
                h = h < 10 ? ('0' + h) : h;
                var minute = date.getMinutes();
                var second = date.getSeconds();
                minute = minute < 10 ? ('0' + minute) : minute;
                second = second < 10 ? ('0' + second) : second;
                return y + '-' + m + '-' + d+' '+h+':'+minute+':'+second;            }
        }

2)js+element-ui实现客户端分页

pageUtil() {
                let totalPage = 0;//总页数
                //总共分几页
                if(this.allData.length/this.pageSize > parseInt(this.allData.length/this.pageSize)){
                    totalPage=parseInt(this.allData.length/this.pageSize)+1;
                }else{
                    totalPage=parseInt(this.allData.length/this.pageSize);
                }
                let startRow = (this.currPage - 1) * this.pageSize;//开始显示的行  31
                let endRow = this.currPage * this.pageSize;//结束显示的行   40
                endRow = (endRow > this.allData.length)? this.allData.length : endRow;    //40
                this.tableData=this.allData.slice(startRow,endRow)

            },

3)匹配多字段

 select u.* from t_user u
        where is_del=0
        <if test="keyword!=null">
            and concat(u.user_name,u.user_pass,u.phone_number) like '%${keyword}%'
        </if>
        order by u.register_time desc

4)让div固定

    position: fixed;

5)sql

    @Select("SELECT COUNT(*) FROM ${reply} WHERE ${pid}=#{id}")

10-31

Java String转换成Timestamp

Timestamp timestamp = Timestamp.valueOf(time);

11-1

后台管理系统基本增删改查功能大致完成,包括前端页面及后端接口

image

11-2

1) input输入框自动获取焦点 只要在该input标签后添加autofocus="autofocus"即可

2)

background-size: length|percentage|cover|contain;
transition: all .5s ease-in-out;z-index: 1;

3)全局前置路由守卫,没登录访问任何页面都会携参数重定向到登录页面,登录成功自动跳转到之前要访问的页面,登录后访问登录页面会重定向到首页

4)修改登录注册方式,放弃之前element的Dialog 对话框改用element的Drawer抽屉组件,提升用户体验

5)使用element的Card卡片组件优化了文章列表的展示及设置背景图片

6)更改input标签的placeholder的样式

主要是要区别不同浏览器的不同css类

在input框中有时想将输入的字和placeholder设为不同的颜色或其它效果,这时就可以用以下代码来对placeholder进行样式设置了。

input::-webkit-input-placeholder{}    /* 使用webkit内核的浏览器 */
input:-moz-placeholder{}                  /* Firefox版本4-18 */
input::-moz-placeholder{}                  /* Firefox版本19+ */
input:-ms-input-placeholder{}           /* IE浏览器 */

注1:冒号前写对应的input或textarea元素等。 注2:placeholder属性是css3中新增加的属性,IE9和Opera12以下版本的CSS选择器均不支持占位文本。 如:

input::-webkit-input-placeholder {
    color: red;
    font-size: 25px;
}

7)如何将input背景色变成透明色

<input type="text" style="background-color:transparent">

11-3

1)让背景图片不承滚动条滚动

  background-attachment: fixed;

2) overflow-y: auto;会让scrollTop的值一直为0

获取元素距视窗顶部的距离

let rt=document.getElementById('ri').getBoundingClientRect().top

11-5

添加图片美化页面

   if (that.$route.query.redirect) {
                            that.$router.push({
                                path:that.$route.query.redirect
                            });
                        }else {
                            that.$router.push({
                                path:'/'
                            });
                        }