前序
在开发社区项目的前端时,根据当前的流行,选择了前后端分离,另外一方面也可以实现后端与前端的解耦。使修改前端代码的时候,无需再打包后台程序。
另外用用vue,提升一下技能。后端程序也得会前端啊。
一些总结
在开发中,总有一些方法在多个组件或者view中使用,每次都需要手动引入对应的方法,导致很繁琐,那么有没有方法不在每个需要的对应方法的组件导入呢?有需求-就会有解决方案。
我们的需求,就是将一些常用或公共的方法,在使用的地方无需重新导入,而是直接引入就可以,那么,这不就是我们java中的全局变量,或者静态类、spring的ioc容器吗?
那么,在vue中,我们应该如何解决这个问题呢?
根据百度,以及vue的官方文档找到了解决方案,可以将我们的通用方法,挂载到vue的prototype(原型)上,从而实现全局使用。
https://cn.vuejs.org/v2/cookbook/adding-instance-properties.html
挂载全局方法
代码示例:
main.js
import * as tools from "@/utils/common"
Vue.prototype.$tools = tools
使用:
this.$tools.toastError("未登录")
父子组件传值
很多时候,我们都会将一个复杂的页面,抽出多个小的组件去编码实现,然后再组装到view。但是这样就会存在一些数据之间的交互问题。常见的场景就是子组件需要父组件的数据、父组件需要子组件的数据、兄弟组件需要兄弟的数据。
根据官方解决方案如下
通过 Prop 向子组件传递数据
1.父组件调用子组件的时候 绑定动态属性
<v-header :title="title"></v-header>
2、在子组件里面通过 props接收父组件传过来的数据
props:['title']
监听子组件事件(子组件 $emit(父组件监听的函数名,数据),@函数名=函数名)
1.父组件定义监听方法
tabItemClick(itemId) {
}
2.绑定监听方法到子组件
<TabList
id="tab-list"
:showRecommen="true"
@tabItemClick="tabItemClick"
></TabList>
3.子组件通过 this.$emit("tabItemClick", this.id);传递数据到父组件监听的函数
父组件主动获取子组件的数据和方法
1.调用子组件的时候定义一个ref
<v-header ref="header"></v-header>
2.在父组件里面通过
this.$refs.header.属性
this.$refs.header.方法
子组件主动获取父组件的数据和方法
this.$parent.数据
this.$parent.方法
部署在非根目录下的问题
本次的社区项目,前台和后台是2个独立的vue项目。部署的时候想根目录下部署前台,然后nginx代理admin路径到后台项目,
在打包完成后,部署到nginx后,发现,后台项目的css,js能都404。猜测是目录的问题,然后查阅百度,找到了解决方案,可以指定publicPath参数和assetsDir参数。
publicPath:该配置能帮助你为项目中的所有资源指定一个基础路径。因此我们部署到正式环境的话,publicPath尽量定义成相对路径('./'),这样打包后就可以部署在任意目录了 。
assetsDir:定义打包后的静态资源目录
alias:定义别名。方法引入src下的内容,从而避免使用大量相对路径
官方文档https://cli.vuejs.org/zh/config/#publicpath
const path = require('path')
function resolve(dir) {
return path.join(__dirname, dir)
}
module.exports = {
// 选项...
publicPath: process.env.NODE_ENV === "production" ? './' : '/',
assetsDir: 'static',
configureWebpack: {
resolve: {
alias: {
'@': resolve('src')
}
}
},
}
Message弹多次的情况(如何只弹一次)
需求:部分提示信息,通过axios的response拦截器进行处理,进行友好的信息提示,但是在实际中,一个页面必定存在多个请求,那么,根据msg的提示信息,就会出现多个。但是这样友好型不够,我只想弹一次。本着有需求就有解决方案,我进行了百度。
解决方案:
定义一个类,这个类用于处理各种信息提示,如成功、错误、警告等。
弹框的时候判断当前页面是否已经存在了弹框的元素,如果已经存在,则不提示,否则可以进行提示。
并且在使用的地方,进行单例。
message.js
import { Message } from 'element-ui'
// 私有属性,只在当前文件可用
const showMessage = Symbol('showMessage')
export default class domMessage {
success(options, single = true) {
this[showMessage]('success', options, single)
}
warning(options, single = true) {
this[showMessage]('warning', options, single)
}
info(options, single = true) {
this[showMessage]('info', options, single)
}
error(options, single = true) {
this[showMessage]('error', options, single)
}
[showMessage](type, options, single) {
if (single) {
// 关键代码,判断当前页是否有el-message标签,如果没有则执行弹窗操作
if (document.getElementsByClassName('el-message').length === 0) {
Message[type](options)
}
} else {
Message[type](options)
}
}
}
使用
方法外初始化,只初始化一次
var messageOnce = new MessageOne();
在需要使用的方法内调用
messageOnce.error({
message: res.data.msg
})
判断对象是否为空
Object.keys(postData).length == 0
Quill富文本编辑器自动获取焦点导致页面自动在最下面
因为要发帖,所以引入了富文本,用的时候挺好用,但是在正式测试的时候,发现点击帖子,就自动到了页面的最下面(因为编辑器在最下面)。咨询了一下前端的朋友,说把编辑器的代码注释掉看看正常不。注释后,发现正常。于是想到了焦点,然后,我就看看富文本有没有默认的配置可以不自动获取焦点,但是我失败了,没有默认的配置。于是只能通过代码来实现。
在Quill初始化后,禁用掉,然后调用失去焦点方法。这里必须禁用,不然还是会获得焦点
this.Quill.enable(false);
this.Quill.blur();
//一大推初始化代码。
//等到完全初始化后,在调用enable方法,接触掉禁用,就可以实现不自动获取焦点了,从而解决了问题
this.Quill.enable(true);
路由守卫
来自vue目标,进行拦截,如果没有权限,直接跳转到登录页
import router from './router'
import { Message } from 'element-ui'
import NProgress from 'nprogress' // progress bar
import 'nprogress/nprogress.css' // progress bar style
import { getToken, removeToken } from '@/utils/auth' // get token from cookie
import getPageTitle from '@/utils/get-page-title'
import { getUserInfo } from "@/api/user"
NProgress.configure({ showSpinner: false }) // NProgress Configuration
const whiteList = ['/login'] // no redirect whitelist
router.beforeEach(async(to, from, next) => {
// start progress bar
NProgress.start()
// set page title
document.title = getPageTitle(to.meta.title)
// determine whether the user has logged in
const hasToken = getToken()
if (hasToken) {
if (to.path === '/login') {
// if is logged in, redirect to the home page
next({ path: '/' })
NProgress.done()
} else {
//发送请求,判断用户是否已经登录
await getUserInfo().then(res => {
console.log(res);
if (res.data != null) {
next()
} else {
next(`/login?redirect=${to.path}`)
removeToken();
}
})
}
} else {
/* has no token*/
if (whiteList.indexOf(to.path) !== -1) {
// in the free login whitelist, go directly
next()
} else {
// other pages that do not have permission to access are redirected to the login page.
next(`/login?redirect=${to.path}`)
NProgress.done()
}
}
})
router.afterEach(() => {
// finish progress bar
NProgress.done()
})