vue全家桶搭建前端页面注意细节及遇到的难题
Posted 昵称正在加载中....
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了vue全家桶搭建前端页面注意细节及遇到的难题相关的知识,希望对你有一定的参考价值。
vue全家桶搭建前端页面注意细节及遇到的难题
一、使用vue脚手架创建项目
- 下载相关插件
二、插件注册具体细节(以下操作是在 main.js)
- element-ui ( PC端组件库 )
// 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 的封装 )
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 ( 响应式布局 )
import 'bootstrap/dist/css/bootstrap.min.css'
- vue-cookie ( 操作 cookie )
import VueCookie from 'vue-cookie'
// 注册
Vue.use(VueCookie)
// 挂载
Vue.prototype.$cookie = VueCookie;
- vue-lazyload ( 图片懒加载 )
import VueLazyLoad from 'vue-lazyload'
Vue.use(VueLazyLoad,{
loading:'/imgs/loading-svg/loading-bars.svg'
})
// 使用时 <img v-lazy="ph.mainImage" alt="" />
- vue-router ( vue 路由)
// 路由引入时要在其他css样式引入后,避免造成上线后,样式未生效。
import router from './router'
new Vue({
router,
render: h => h(App),
}).$mount('#app')
// router.js
import Vue from 'vue'
import Router from 'vue-router'
const router = new Router({
routes: [] // 配置路由 注意:是 routes 不是 router
})
export default router
- vuex ( 状态管理 )
import store from './store/index'
new Vue({
store,
render: h => h(App),
}).$mount('#app')
- index 是 vuex 的入口文件。具体配置
三、路由、页面、及其组件配置
- 前期在搭建静态页面及组件时,并没有发现太大的问题,这里就不细写,懂的都懂,哈哈哈哈!
- 主要是路由这部分,一个权限的问题:没有登录前是不能进入到主页面的。
- 查阅 vue 官方文档 vue-router 核心插件库中有 router.beforeEach() 方法(全局前置守卫)可以解决这个问题。
- 接下来就是判断是否登录的标志,标志是在后端开发的时候,用户登录成功,后端给 cookie 设置一个好密钥。因此只要判断 cookie 中的某一个值是否存在即可。
/*
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 中直接引入。
import Cookie from 'vue-cookie'
- 还有一点:后端设置 cookie 时 httpOnly 不能设置为 true, 否则前端是无法获取到的。
四、跳转到同一页面时,页面数据不刷新
- 业务描述:用户可以进入到其他用户主页面时,出现了数据不更新的情况。
// router.js
path: '/Otherprofile/:username',
- 查阅官方资料得到的结论是:vue跳转到同一路径时,路由参数改变,数据不更新,最主要的地方是:引用了相同的组件的时候,页面就无法更新。
- 网上的解决方法有很多:
- 方案一:watch监听路由参数变化(不包括传递的参数),并重新渲染(谨慎选择);
- 方案二:provide和inject结合使用(推荐使用);
- 方案三:直接在 app.vue 中的 <router-view> 添加一个 key 值
<template>
<div id="app">
<!--
通过绑定一个fullPath, 直接识别页面路径的完整地址,
当地址发生改变(包括参数改变)则重新渲染页面。
-->
<router-view :key="$route.fullPath"></router-view>
</div>
</template>
- 而我一开始选择的方案是:结合方案一以及方案二的一部分原理:父组件通过监听 route 的变化,一旦发生改变,这些方案二的相关操作。
- 由于前期代码不断修改后,没有保存代码,具体代码无法展示。
- 但这种方法,到后期上线时,出现了 bug:进入到其他人主页后,跳转到个人首页时,无法访问到编译后的 js 文件(第十点会具体提到)。
- 最终我选择了方案三。
五、页面刷新导致 vuex 数据丢失
- 业务描述:由于对于当前用户的信息在前端是比较重要的(很多请求都需要用户信息的凭证)。
- 因此想到了用 vuex 状态管理。
- 到了后期,又出现了一个问题,业务需要时不时刷新页面,这就导致了 vuex 数据丢失。
- 查阅资料有一个解决方法:结合 sessionStorage 以及监听器。
- 监听刷新时,将 vuex 数据存入到 sessionStorage 中。
// 根据业务,我在 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,完全符合业务要求。
<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>
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
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 两种方式:
path: '/Otherprofile',
path: '/:username',
- 我选择前者,然后再跳转路由时添加 username 即可:
this.$router.push({
path: "/Otherprofile",
query: {
otherName,
},
});
// 获取参数
this.$route.query.otherName
- 此时,第四点使用的监听路由变化就不能生效了,因为这里访问的路径都一样,只是传递的参数不一样,因此只能选择方案三。
- 如果选择后者,按理论也可以使用之前的方案,但在我的项目中,出现问题,有时会跳转到其他页面。
- 启动项目:
- 在本地是不会出现这个问题的,重新打包也会出现这个问题。但是,不知道被我怎么弄的,现在就没有出现这个问题。
- 查资料说是需要配置webpack,webpack 我也不熟,而且在 vue.config.js 中的配置方法跟 webpack 还有点不一样。
- 最终这个 bug 就不了了之。
十一、部分效果图
- 主页
- 广场页
- 设置页
- 个人主页
十二、总结
- 不足的地方:
原先设计是发布微博是可以添加图片,后期完善是想可以上传视频的。设想是利用阿里OSS(Object Storage Service)对象存储服务,原理及使用都会了点这里,但使用图片链接直接在浏览器访问时,是不能访问的,只会下载到本地电脑。而要实现这个功能,需要绑定域名,且域名需要备案,备案目前一直还过不了。 - 体会:
在写前端代码时遇到很多问题,一度真的想放弃,但过了几天还是埋头苦干。遇到问题就查资料,有时是自己粗心大意写错代码,有时是真的有坑,开发前期不知道,没有去避开这些坑,总体上开发过程中磕磕碰碰。特别是上线打包部署这部分,本身就对这部分一点基础都没有,就是摸着石头过河,一步步试。
以上是关于vue全家桶搭建前端页面注意细节及遇到的难题的主要内容,如果未能解决你的问题,请参考以下文章
实战Vue全家桶(vue + axios + vue-router + vuex)搭建移动端H5项目