x

一、使用vue脚手架创建项目

点击访问项目

不懂点这里

下载源码

  • 下载相关插件

在这里插入图片描述


二、插件注册具体细节(以下操作是在 main.js)

  • element-ui ( PC端组件库 )
1
2
3
4
5
6
7
8
9
10
// main.js文件中
import 'element-ui/lib/theme-chalk/index.css'
// 按需加载
import { Message } from 'element-ui'
import { Button } from 'element-ui'
// 在 html 中直接<el-button></el-button> 只要注册即可无需挂载
Vue.use(Button)

//挂载 在js环境下使用直接可这样使用 this.$message.error("错误");
Vue.prototype.$message = Message
  • axios ( ajax 的封装 )
1
2
3
4
5
6
7
8
9
10
11
import axios from 'axios'

// 在请求地址前加api (如请求localhost:8080/a 实际请求路由 localhsot:8080/api/a)
axios.defaults.baseURL = '/api';
// 设置超时时间
axios.defaults.timeout = 8000;

// axios 挂载 vue 原型上 后期直接使用 this.axios 直接使用即可
Vue.prototype.axios = axios

// 发请求时直接 this.axios.get("/a", {params});
  • bootstap ( 响应式布局 )
1
import 'bootstrap/dist/css/bootstrap.min.css'
  • vue-cookie ( 操作 cookie )
1
2
3
4
5
import VueCookie from 'vue-cookie'
// 注册
Vue.use(VueCookie)
// 挂载
Vue.prototype.$cookie = VueCookie;
  • vue-lazyload ( 图片懒加载 )
1
2
3
4
5
6
7
8
import VueLazyLoad from 'vue-lazyload'

Vue.use(VueLazyLoad,{
loading:'/imgs/loading-svg/loading-bars.svg'
})

// 使用时 <img v-lazy="ph.mainImage" alt="" />

  • vue-router ( vue 路由)
1
2
3
4
5
6
// 路由引入时要在其他css样式引入后,避免造成上线后,样式未生效。
import router from './router'
new Vue({
router,
render: h => h(App),
}).$mount('#app')
1
2
3
4
5
6
7
// router.js
import Vue from 'vue'
import Router from 'vue-router'
const router = new Router({
routes: [] // 配置路由 注意:是 routes 不是 router
})
export default router
  • vuex ( 状态管理 )
1
2
3
4
5
import store from './store/index'
new Vue({
store,
render: h => h(App),
}).$mount('#app')

三、路由、页面、及其组件配置

  • 前期在搭建静态页面及组件时,并没有发现太大的问题,这里就不细写,懂的都懂,哈哈哈哈!
  • 主要是路由这部分,一个权限的问题:没有登录前是不能进入到主页面的
  • 查阅 vue 官方文档 vue-router 核心插件库中有 router.beforeEach() 方法(全局前置守卫)可以解决这个问题。
  • 接下来就是判断是否登录的标志,标志是在后端开发的时候,用户登录成功,后端给 cookie 设置一个好密钥。因此只要判断 cookie 中的某一个值是否存在即可
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/*
to(去哪里) from(从哪里来)
next(只是一个方法而已,说白了就是让其通过或者跳转到相对应路径)
*/
router.beforeEach((to, from, next) => {
if (to.path == "/login") {
next()
} else if (to.path == "/register") {
next()
} else {
if (Cookie.get(constant.COOKIE)) {
next()
} else {
next('/login')
}
}
})
  • 在这里我遇到一个问题:在 main.js 中我将 vue-cookie 挂载到 vue 实例上了,所以我自然而然的使用 this.$cookie.get(constant.COOKIE); 但这样写是不对的。因为在 router 中 this 并不是指向 vue 的,因此只能将插件直接在 router.js 中直接引入
1
import Cookie from 'vue-cookie'
  • 还有一点:后端设置 cookie 时 httpOnly 不能设置为 true, 否则前端是无法获取到的

四、跳转到同一页面时,页面数据不刷新

  • 业务描述:用户可以进入到其他用户主页面时,出现了数据不更新的情况。
1
2
// router.js
path: '/Otherprofile/:username',
  • 查阅官方资料得到的结论是:vue跳转到同一路径时,路由参数改变,数据不更新,最主要的地方是:引用了相同的组件的时候,页面就无法更新
  • 网上的解决方法有很多:
  • 方案一:watch监听路由参数变化(不包括传递的参数),并重新渲染(谨慎选择);
  • 方案二:provide和inject结合使用(推荐使用);
  • 方案三:直接在 app.vue 中的 <router-view> 添加一个 key 值
1
<template>  <div id="app">  <!--    通过绑定一个fullPath, 直接识别页面路径的完整地址,    当地址发生改变(包括参数改变)则重新渲染页面。  -->    <router-view :key="$route.fullPath"></router-view>  </div></template>
  • 而我一开始选择的方案是:结合方案一以及方案二的一部分原理:父组件通过监听 route 的变化,一旦发生改变,这些方案二的相关操作
  • 由于前期代码不断修改后,没有保存代码,具体代码无法展示。
  • 但这种方法,到后期上线时,出现了 bug:进入到其他人主页后,跳转到个人首页时,无法访问到编译后的 js 文件(第十点会具体提到)。
  • 最终我选择了方案三

五、页面刷新导致 vuex 数据丢失

  • 业务描述:由于对于当前用户的信息在前端是比较重要的(很多请求都需要用户信息的凭证)。
  • 因此想到了用 vuex 状态管理
  • 到了后期,又出现了一个问题,业务需要时不时刷新页面,这就导致了 vuex 数据丢失
  • 查阅资料有一个解决方法:结合 sessionStorage 以及监听器
  • 监听刷新时,将 vuex 数据存入到 sessionStorage 中。
1
// 根据业务,我在 app.js中设置监听器 window.addEventListener("beforeunload", () => {      const state = this.$store.state;      window.sessionStorage.setItem("store", JSON.stringify(state));    });     init() {    let store = window.sessionStorage.getItem("store")    if (store) {      this.$store.dispatch("saveUserInfo", JSON.parse(store).userInfo);      // 避免造成污染      sessionStorage.removeItem("store");     } else {      // 获取用户信息      this.axios.get("/user/isLogin").then((res) => {      if (res) {        this.$store.dispatch("saveUserInfo", res);      }    });   } }
  • 但项目完成后,细想其实这个功能使用 vuex 是不对的vuex 只要用在一个变量值可以控制多个页面的行为,或者多个变量控制一个页面
  • 比如:项目中有一个功能点(进入到其他人主页是判断当前用户是否关注了此人)使用了vuex 我认为就适合。
  • 所以,最开始用户信息就应该使用 sessionStorage 即可

六、多个请求发送出现相互依赖

  • 业务描述:用户进入到主页面时,需要发送多条请求,但后俩条请求的参数时基于第一条请求来的数据(第一条获取用户信息,二三条通过用户信息获取关注人以及粉丝信息)。
  • 解决方法:(1)直接链式调用、(2)根据用户需求在发送二三条请求(用户要查看粉丝或者关注人时,触发点击事件在发送请求。)

七、@功能

  • 业务描述:发布微博时可以@自己所关注的用户。
  • 可以原生开发,但为了开发速度,我使用用了一个插件 vue-at,完全符合业务要求。
1
<at-ta :members="members" name-key="fullName">     <template v-slot:item="s">       <img :src="s.item.picture" />       <span>{{ s.item.nickName }} - {{ s.item.userName }}</span>     </template>     <el-input       id="textarea"       type="textarea"       class="element-editor resizeNone"       v-model="fullcontent"       rows="7"      ></el-input></at-ta>
1
import AtTa from "vue-at/dist/vue-at-textarea";export default {  name: "inputitem",  data() {    return {      members: [],      fullcontent: "",    };  },}

八、数据渲染,无法渲染监听事件

  • 业务描述:发布微博可以@用户,向后端发送请求获取的是纯文本,因此前端需要用正则表达式来匹配,进而将其嵌套到a标签中,用户点击时可以跳转到相应个人主页
  • 正则表达式匹配成功,并且添加了点击事件,但使用 {{content}} 是无法渲染的

在这里插入图片描述

  • 后来想到一种方法直接在 a 添加 href 属性,可以跳转,但在个人主页我是通过检测 router 路由的变化,来更新页面的,而使用 href 是无法同步到 router 的路由的,因此这个方法被否决了。

查阅 vue 官方文档,看到可以使用渲染函数 render

1
render(createElement) {   // contentList 是你要渲染的内容数组(已经通过正则表达式匹配过的)    return createElement(contentList)  },
  • 但在我的项目中,很难去使用,要考虑到很多问题,比如说我如何将对象数组中的某一个字段(内容)放到同一个数组中,渲染完毕后,又如何分发到对应对象数组中,这部分应该是可以实现的。(本人基础也不是很牢固,需要去查资料才可以实现)

九、使用 history 模式上线,导致某些资源访问不到

  • 项目如果不是部署在根路径下的就必须使用 history 模式。比如localhost:8080/login(根路径下) localhost:8080/weibo/login (子路径下)
  • 不使用 history 模式时,会在访问路径下添加 #
  • 而我主要出现的问题是在,首先对于前后端代码上线我是零基础的,一直处在摸索中。

在这里插入图片描述

  • 第一个处错的地方:router.js 中的 base 值应该是你 nginx 中的访问路径值,我写成了项目在服务器的地址。(我项目地址和访问地址是不一样的)
    在这里插入图片描述
  • 第一个地方改好后,运行项目是可以访问的,但又报了一个错误
    在这里插入图片描述
  • 查资料,可能是使用了 history 模式下,导致某些资源访问不到。这个地方花费了最长时间。
  • 其实只要修改 vue.config.js 即可, 内部就是修改 webpack 的打包配置。但我从来没有接触过 webpack 。也造成很大困难。
  • 项目只要修改 publicPath: ‘./‘,即可。按我的理解是访问静态资源是在上一层目录,不使用 history 就正常访问,如今你加了子路径,因此再访问静态资源时需要跳转到上一层
  • 还有一点访问一些静态资源尽量放在 public 文件夹中,而不是放在 assets 文件中,防止打包时造成不必要的错误
  • 在 app.Vue 全局引入时
    在这里插入图片描述

十、解决第四点埋下的坑

  • 前面几点解决后,上线部署,此时出现报了这个错误

在这里插入图片描述

  • 不是一运行就报错的,而是进入到其他人主页后,跳转到其他页面就报这个错误
  • 意思是没有访问到编译后的 js 文件

在这里插入图片描述

  • 后来看了请求的地址和其他页面请求的地址,看到了多了一个 /Otherprofile 路径。
  • 报着试一试的态度访问了 /weibo/js/chunk-07853974.d3c97a8d.js

在这里插入图片描述

  • 很明显是路径访问错了,然后接下来:我就去看了路由的配置

在这里插入图片描述

  • 很明显:其他人主页是要进入到俩层路径的,而主页要进入一层路径。但这还不是最关键的。最关键的是 vue.config.js 中静态访问路径是访问上一级目录

在这里插入图片描述

  • 因此导致说:在一层路径下的上一级目录(/weibo)可以被 nginx 识别到,进而访问到 js 文件。而二层目录的上一级目录是 Otherprofile,不是 weibo,得是上上层目录。
  • 因此解决方法是,进入到其他人主页不能使用俩级路径
  • 此时修改 router.js 两种方式:
1
path: '/Otherprofile',path: '/:username',
  • 我选择前者,然后再跳转路由时添加 username 即可:
1
this.$router.push({          path: "/Otherprofile",          query: {            otherName,          },        });  // 获取参数 this.$route.query.otherName
  • 此时,第四点使用的监听路由变化就不能生效了,因为这里访问的路径都一样,只是传递的参数不一样,因此只能选择方案三。
  • 如果选择后者,按理论也可以使用之前的方案,但在我的项目中,出现问题,有时会跳转到其他页面。
  • 启动项目:
    在这里插入图片描述
  • 在本地是不会出现这个问题的,重新打包也会出现这个问题。但是,不知道被我怎么弄的,现在就没有出现这个问题。
  • 查资料说是需要配置webpack,webpack 我也不熟,而且在 vue.config.js 中的配置方法跟 webpack 还有点不一样。
  • 最终这个 bug 就不了了之。

十一、部分效果图

  • 主页
    在这里插入图片描述
  • 广场页
    在这里插入图片描述
  • 设置页
    在这里插入图片描述
  • 个人主页
    在这里插入图片描述

    十二、总结

  • 不足的地方:
    原先设计是发布微博是可以添加图片,后期完善是想可以上传视频的。设想是利用阿里OSS(Object Storage Service)对象存储服务,原理及使用都会了点这里,但使用图片链接直接在浏览器访问时,是不能访问的,只会下载到本地电脑。而要实现这个功能,需要绑定域名,且域名需要备案,备案目前一直还过不了。
  • 体会:
    在写前端代码时遇到很多问题,一度真的想放弃,但过了几天还是埋头苦干。遇到问题就查资料,有时是自己粗心大意写错代码,有时是真的有坑,开发前期不知道,没有去避开这些坑,总体上开发过程中磕磕碰碰。特别是上线打包部署这部分,本身就对这部分一点基础都没有,就是摸着石头过河,一步步试。