上下固定,中间滚动布局(FLEX)

<div id="app">
<div class="header"></div>
<div class="views"></div>
<div class="footer"></div>
</div>
<style>
#app{display: flex;flex-direction: column;height: 100%;}
.views{flex: 1; overflow-y: scroll;-webkit-overflow-scrolling: touch;} /*-webkit-overflow-scrolling: touch; 解决苹果手机下网页滑动不顺畅问题*/
.header{} /*高度随意设置*/
.footer{} /*高度随意设置*/
</style>

Vue插件封装(loading实例)

src/omponents/loading/Loading.vue
<template>
<div class="loading" v-show="show">
<i class="i-loading"></i>
</div>
</template> <script>
export default {
props: {
show: Boolean
}
}
</script>
<style lang="scss" scoped>
.loading{
width: 200px;
height: 200px;
position: fixed;
left: 0;
right: 0;
bottom: 0;
top: 0;
margin: auto;
border-radius: 6px;
background: rgba(0,0,0,0.6);
display: flex;
justify-content: center;
align-items: center;
z-index: 999;
}
.i-loading {
width: 90px;
height: 90px;
display: inline-block;
vertical-align: middle;
-webkit-animation: loading 1s steps(12, end) infinite;
animation: loading 1s steps(12, end) infinite;
background: transparent url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxMjAiIGhlaWdodD0iMTIwIiB2aWV3Qm94PSIwIDAgMTAwIDEwMCI+PHBhdGggZmlsbD0ibm9uZSIgZD0iTTAgMGgxMDB2MTAwSDB6Ii8+PHJlY3Qgd2lkdGg9IjciIGhlaWdodD0iMjAiIHg9IjQ2LjUiIHk9IjQwIiBmaWxsPSIjRTlFOUU5IiByeD0iNSIgcnk9IjUiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDAgLTMwKSIvPjxyZWN0IHdpZHRoPSI3IiBoZWlnaHQ9IjIwIiB4PSI0Ni41IiB5PSI0MCIgZmlsbD0iIzk4OTY5NyIgcng9IjUiIHJ5PSI1IiB0cmFuc2Zvcm09InJvdGF0ZSgzMCAxMDUuOTggNjUpIi8+PHJlY3Qgd2lkdGg9IjciIGhlaWdodD0iMjAiIHg9IjQ2LjUiIHk9IjQwIiBmaWxsPSIjOUI5OTlBIiByeD0iNSIgcnk9IjUiIHRyYW5zZm9ybT0icm90YXRlKDYwIDc1Ljk4IDY1KSIvPjxyZWN0IHdpZHRoPSI3IiBoZWlnaHQ9IjIwIiB4PSI0Ni41IiB5PSI0MCIgZmlsbD0iI0EzQTFBMiIgcng9IjUiIHJ5PSI1IiB0cmFuc2Zvcm09InJvdGF0ZSg5MCA2NSA2NSkiLz48cmVjdCB3aWR0aD0iNyIgaGVpZ2h0PSIyMCIgeD0iNDYuNSIgeT0iNDAiIGZpbGw9IiNBQkE5QUEiIHJ4PSI1IiByeT0iNSIgdHJhbnNmb3JtPSJyb3RhdGUoMTIwIDU4LjY2IDY1KSIvPjxyZWN0IHdpZHRoPSI3IiBoZWlnaHQ9IjIwIiB4PSI0Ni41IiB5PSI0MCIgZmlsbD0iI0IyQjJCMiIgcng9IjUiIHJ5PSI1IiB0cmFuc2Zvcm09InJvdGF0ZSgxNTAgNTQuMDIgNjUpIi8+PHJlY3Qgd2lkdGg9IjciIGhlaWdodD0iMjAiIHg9IjQ2LjUiIHk9IjQwIiBmaWxsPSIjQkFCOEI5IiByeD0iNSIgcnk9IjUiIHRyYW5zZm9ybT0icm90YXRlKDE4MCA1MCA2NSkiLz48cmVjdCB3aWR0aD0iNyIgaGVpZ2h0PSIyMCIgeD0iNDYuNSIgeT0iNDAiIGZpbGw9IiNDMkMwQzEiIHJ4PSI1IiByeT0iNSIgdHJhbnNmb3JtPSJyb3RhdGUoLTE1MCA0NS45OCA2NSkiLz48cmVjdCB3aWR0aD0iNyIgaGVpZ2h0PSIyMCIgeD0iNDYuNSIgeT0iNDAiIGZpbGw9IiNDQkNCQ0IiIHJ4PSI1IiByeT0iNSIgdHJhbnNmb3JtPSJyb3RhdGUoLTEyMCA0MS4zNCA2NSkiLz48cmVjdCB3aWR0aD0iNyIgaGVpZ2h0PSIyMCIgeD0iNDYuNSIgeT0iNDAiIGZpbGw9IiNEMkQyRDIiIHJ4PSI1IiByeT0iNSIgdHJhbnNmb3JtPSJyb3RhdGUoLTkwIDM1IDY1KSIvPjxyZWN0IHdpZHRoPSI3IiBoZWlnaHQ9IjIwIiB4PSI0Ni41IiB5PSI0MCIgZmlsbD0iI0RBREFEQSIgcng9IjUiIHJ5PSI1IiB0cmFuc2Zvcm09InJvdGF0ZSgtNjAgMjQuMDIgNjUpIi8+PHJlY3Qgd2lkdGg9IjciIGhlaWdodD0iMjAiIHg9IjQ2LjUiIHk9IjQwIiBmaWxsPSIjRTJFMkUyIiByeD0iNSIgcnk9IjUiIHRyYW5zZm9ybT0icm90YXRlKC0zMCAtNS45OCA2NSkiLz48L3N2Zz4=) no-repeat;
background-size: 100%;
}
@keyframes loading {
0% {
-webkit-transform: rotate3d(0, 0, 1, 0deg);
transform: rotate3d(0, 0, 1, 0deg);
}
100% {
-webkit-transform: rotate3d(0, 0, 1, 360deg);
transform: rotate3d(0, 0, 1, 360deg);
}
}
</style> src/omponents/loading/index.js
<script>
import LoadingComponent from './loading'
let $vm
export default {
install (Vue, options) {
if (!$vm) {
const LoadingPlugin = Vue.extend(LoadingComponent)
$vm = new LoadingPlugin({
el: document.createElement('div')
})
console.log($vm)
}
$vm.show = false
let loading = {
show (text) {
$vm.show = true
$vm.text = text
document.body.appendChild($vm.$el)
},
hide () {
$vm.show = false
}
}
if (!Vue.$loading) {
Vue.$loading = loading
}
Vue.mixin({
created () {
this.$loading = Vue.$loading
}
})
}
}
//使用
import Loading from '@/components/loading/index.js' //loading 插件
Vue.use(Loading) //使用loading插件
Vue.$loading.show() //显示
Vue.$loading.hide() //隐藏
</script>

axios全局路由拦截及结合promise对axios请求进行处理

src/utils/request.js
import axios from 'axios'
import {Notification, MessageBox} from 'element-ui'
import store from '@/store'
import {getToken} from '@/utils/auth' axios.defaults.headers['Content-Type'] = 'application/json;charset=utf-8'
// 创建axios实例
const service = axios.create({
// axios中请求配置有baseURL选项,表示请求URL公共部分
baseURL: process.env.VUE_APP_BASE_API,
// 超时
timeout: 10000
})
// request拦截器
service.interceptors.request.use(
config => {
if (getToken()) {
config.headers['Authorization'] = 'Bearer ' + getToken() // 让每个请求携带自定义token 请根据实际情况自行修改
}
return config
},
error => {
Promise.reject(error)
}
) // 响应拦截器
service.interceptors.response.use(res => {
const code = res.data.code
if (code === 401) {
MessageBox.confirm(
'登录状态已过期,您可以继续留在该页面,或者重新登录',
'系统提示',
{
confirmButtonText: '重新登录',
cancelButtonText: '取消',
type: 'warning'
}
).then(() => {
store.dispatch('LogOut').then(() => {
location.reload() // 为了重新实例化vue-router对象 避免bug
})
})
} else if (code !== 200) {
Notification.error({
title: res.data.msg
})
return Promise.reject('error')
} else {
return res.data
}
},
error => {
Message({
message: error.message,
type: 'error',
duration: 5 * 1000
})
return Promise.reject(error)
}
) export default service src/api.js
import request from '@/utils/request'
// AXIOS GET请求 // get
export function listConfig(query) {
return request({
url: '/system/config/list',
method: 'get',
params: query
})
}
// post
export function addConfig(data) {
return request({
url: '/system/config',
method: 'post',
data: data
})
}

  

路由的其他一些配置

router.beforeEach((to, from, next) => {
// 动态更改页面title
if (to.meta.title) {
document.title = to.meta.title
} // 验证是否需要登陆
if (to.meta.requireAuth && JSON.stringify(store.state.user) === '{}') {
next({ name: 'signIn' })
} // 如果登录状态进入登录页面则,返回到个人中心页面
if (JSON.stringify(store.state.user) !== '{}') {
if (to.name === 'signIn' || to.name === 'resetPassword' || to.name === 'mobileLogin') {
next({ name: 'personal', query: { type: 'records' } })
}
}
next()
})

解决移动端click300ms问题

安装
npm install fastclick --save
使用
import fastclick from 'fastclick'
fastclick.attach(document.body)

Vue父子组件通讯

父向子传递参数
Parent.vue(父组件)
<template>
<div>
<Child :name="name"></Child>
</div>
</template>
<script>
import Child from './Child'
export default{
components:{
Child
},
data(){
return{
name:'hello'
}
}
}
</script>
Child.vue(子组件)
<template>
<div>
<!-- 这里的name接收了父组件传过来的参数,这里会变成hello -->
{{name}}
</div>
</template>
<script>
export default{
props:{
name:String
}
}
</script> 子向父传递参数 Child.vue(子组件)
<template>
<div>
<button @click="toParentMsg()">我要向父节点传递参数</button>
</div>
</template>
<script>
export default{
method:{
toParentMsg(){
this.$emit('listenToChildEvent','我是要向父组件传送的数据') //listenToChildEvent 自定义事件,后面需要再父组件接收这个自定义事件
}
}
}
</script>
Parent.vue(父组件)
<template>
<div>
<Child @listenToChildEvent = "receiveChildMsg"></Child>
</div>
</template>
<script>
import Child from './Child'
export default{
components:{
Child
},
data(){ },
method:{
receiveChildMsg(val){
console.log(val) //我是要向父组件传送的数据
}
}
}
</script>

对函数进行封装全局使用

src/utils/global.js //公共方法写在这
exports.install = function (Vue, options) {
/**
* 对小数位进行格式化
* @data 数据
* @num 格式位数
* */
Vue.filter('decimalPlaceFormat', function (data, num) {
if (!(data && num)) return ''
return Number(data).toFixed(num)
});
} src/main.js //引用安装
import global from './utils/global'
Vue.use(global)

对指令封装全局使用

src/directive/hasPermiss.js
/**
* 按钮权限控制
* */ import store from './../store'
export default {
inserted(el,binding) {
const {value} = binding;
const btnPermiss = store.getters.btnPermiss;
let status = btnPermiss.some(item => item == value);
if(!status){
el.parentNode && el.parentNode.removeChild(el);
}
}
} src/directive/index.js
import hasPermiss from './hasPermiss'
const install = function(Vue) {
Vue.directive('hasPermiss',hasPermiss)
}
if (window.Vue) {
window['hasPermiss'] = hasPermiss;
Vue.use(install);
}
export default install src/main.js
import install from './directive'
Vue.use(global);

  

VUEX模块使用

Vuex数据操作及数据持久化

使用vuex-persistedstate插件
const store = new Vuex.Store({
state: {
// 用户信息
user: {},
// 分类页数据筛选
videoListFilterTerm: {
catId: 0,
courseId: 0,
software: 0,
diff: 0,
sort: 3,
page: 1
}
},
//获取state数据
getters: {
getUser (state) {
return state.user
}
},
//操作state数据
mutations: {
setUser (state, user) {
state.user = user
},
setVideoListFilterTerm (state, videoListFilterTerm) {
state.videoListFilterTerm = videoListFilterTerm
}
},
//触发mutations函数
actions: {
setUser ({ commit }, user) {
commit('setUser', user)
},
setVideoListFilterTerm ({ commit }, videoListFilterTerm) {
commit('setVideoListFilterTerm', videoListFilterTerm)
}
},
//插件配置
plugins: [createPersistedState({
storage: window.localStorage,
reducer (val) {
return {
user: val.user
}
}
})]
})

Vue m3u8视频播放配置

播放m3u8视频需要用到 videojs-contrib-hls插件
安装 npm install videojs-contrib-hls --save
导入import 'videojs-contrib-hls'

Vue-router 实现模块化加载

使用该方式导入组件,打包模块会自动把组件进行模块化打包
const xxx = () => import('@/views/xxx')

Vue路由切换增加动画效果

90sheji-video/src/App.vue
<template>
<div id="app">
<transition name="fade" mode="out-in">
<router-view />
</transition>
</div>
</template> <script>
export default {
name: 'App'
}
</script>
src/components/layout/Layout.vue
<template>
<div class="layout flex">
<Header/>
<transition name="fade-transform" mode="out-in">
<keep-alive>
<router-view :key="key"/>
</keep-alive>
</transition>
<Footer/>
</div>
</template>
<script>
import Footer from '@/components/common/Footer'
import Header from '@/components/common/Header'
export default {
data () {
return {
catId: ''
}
},
components: {
Footer,
Header
},
computed: {
key () {
return this.$route.name ? this.$route.name : this.$route.fullPath
}
}
}
</script>
<style>
/*********************动画·start**************************/ /* fade */
.fade-enter-active,
.fade-leave-active {
transition: opacity 0.2s;
} .fade-enter,
.fade-leave-active {
opacity: 0;
} /* fade-transform */
.fade-transform-leave-active,
.fade-transform-enter-active {
transition: all 0.2s;
} .fade-transform-enter {
opacity: 0;
transform: translateX(-20px);
} .fade-transform-leave-to {
opacity: 0;
transform: translateX(20px);
} /* breadcrumb transition */
.breadcrumb-enter-active,
.breadcrumb-leave-active {
transition: all 0.2s;
} .breadcrumb-enter,
.breadcrumb-leave-active {
opacity: 0;
transform: translateX(20px);
} .breadcrumb-move {
transition: all 0.2s;
} .breadcrumb-leave-active {
position: absolute;
} /*********************动画·end**************************/
</style>
组件切换有两种情况,一种是兄弟与兄弟组件切换,一种是子组件与父组件之间切换,所以这里转场动画用的不一样,所以贴出了两个组件用法
<keep-alive> 增加这个标签表示组件可以被缓存起来,强烈加上
<router-view :key="key"/> 前面用了组件缓存,所以路由视图的key一定要加上,不然路由和页面有些会不匹配

vue使用官方脚手架打包上线配置

/config/index.js
build: {
// Template for index.html
index: path.resolve(__dirname, '../dist/index.html'),//入口文件
// Paths
assetsRoot: path.resolve(__dirname, '../dist'),//编译后所有需要部署的文件都放到了这里
assetsSubDirectory: 'public',//静态资源存放的文件目录
assetsPublicPath: './',// ./是相对路径,/是绝对路径,这里改为相对路径,不然打包后上线图片访问不了
productionSourceMap: true,//是否开启SourceMap压缩
devtool: '#source-map',
productionGzip: false,//是否开启Gzip压缩
productionGzipExtensions: ['js', 'css'],//Gzip压缩
bundleAnalyzerReport: process.env.npm_config_report
}

后端解决跨域配置

resp.setHeader("Access-Control-Allow-Origin", "*");
resp.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");

package.json文件中dependencies与devDependencies的区别

dependencies:打包上线需要用到的插件 使用npm inatall --save xxx 安装插件
devDependencies:开发环境需要用到的插件 使用npm install --save-dev xxx 安装插件

前端移动端开发总结(Vue)的更多相关文章

  1. 大前端时代搞定PC/Mac端开发,我有绝招

    如果你是一位前端开发工程师,对"跨平台"一词应该不会感到陌生.像常见的前端框架:比如React.Vue.Angular,它们可以做网页端,也可以做移动端,但很少能做到跨PC.Mac ...

  2. 基于 Laravel 开发 ThinkSNS+ 中前端的抉择(webpack/Vue)踩坑日记【ThinkSNS+研发日记系列】

    在上一篇文章< ThinkSNS+基于Laravel master分支,从1到 0,再到0.1>,简单的介绍了 社群系统ThinkSNS+ ,这里分享在开发过程中,前端选择的心理活动. L ...

  3. 前端工程化(三)---Vue的开发模式

    从0开始,构建前后端分离应用 导航 前端工程化(一)---工程基础目录搭建 前端工程化(二)---webpack配置 前端工程化(三)---Vue的开发模式 前端工程化(四)---helloWord ...

  4. 基于 Laravel 开发 ThinkSNS+ 中前端的抉择(webpack/Vue)踩坑日记

    在上一篇文章< ThinkSNS+基于Laravel master分支,从1到 0,再到0.1>,简单的介绍了 ThinkSNS+ ,这里分享在开发过程中,前端选择的心理活动. Larav ...

  5. 开发基于vue前端框架下的系统的UI自动化,记录总结踩的坑

    在使用了pytest完成了一个系统的UI自动化后,因为系统的前端框架,是 基于VUE写的,这就让我编写脚本的时候踩了些坑. 无法用JS 修改标签属性,从而进行的操作 比如上传图片,我们的上传是这样子的 ...

  6. 大前端全栈CSS3移动端开发

    作者声明:本博客中所写的文章,都是博主自学过程的笔记,参考了很多的学习资料,学习资料和笔记会注明出处,所有的内容都以交流学习为主.有不正确的地方,欢迎批评指正 本节课学习视频来源:https://ww ...

  7. GraphQL-前端开发的利剑与桥梁

    GraphQL-前端开发的利剑与桥梁 基本概念 GraphQL GraphQL 是一种用于 API 的查询语言,由Facebook开发和开源,是使用基于类型系统来执行查询的服务端运行时(类型系统由你的 ...

  8. AppBoxFuture(六): 前端组件化开发

      前面几篇都是在介绍结构化与非结构化的数据存储,本篇换换口味介绍一下框架是如何实现前端组件化开发的.首先得感谢Vue.ElementUI等优秀的前端开源项目,这些项目帮助作者快速实现了框架的两个前端 ...

  9. Web前端,HTML5开发,前端资源,前端网址,前端博客,前端框架整理 - 转改

    Web前端/H5开发,前端资源,前端网址,前端博客,前端框架整理 综合类 前端知识体系 前端知识结构 Web前端开发大系概览 Web前端开发大系概览-中文版 Web Front-end Stack v ...

随机推荐

  1. RabbitMq--4--集群(转载)

    RabbitMQ消息服务用户手册 1 基础知识 1.1 集群总体概述 Rabbitmq Broker集群是多个erlang节点的逻辑组,每个节点运行Rabbitmq应用,他们之间共享用户.虚拟主机.队 ...

  2. kubernetes容器集群管理部署master节点组件

    集群部署获取k8s二进制包 [root@master ~]# wget https://dl.k8s.io/v1.15.0/kubernetes-server-linux-amd64.tar.gz [ ...

  3. 分支结构if 语句举例

  4. Nginx动静分离基本概述

    Nginx动静分离基本概述 动静分离,通过中间将动静分离和静态请求进行分离: 通过中间件将动态请求和静态请求分离,可以建上不必要的请求消耗,同时能减少请求的延时. 通过中间件将动态请求和静态请求分离, ...

  5. 一 shell编程

    好啦.从今天开始我们转入shell编程的行列.从鸟哥私房菜中,已经学到了一些shell编程的皮毛,这两个月打算系统的学习,学会,学熟练.加油吧 bash shell [root@localhost s ...

  6. java23种设计模式(二)-- 建造者模式和原型模式

    一.建造者模式 将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创造不同的表示. 特点: (1).在某些属性没有赋值之前,复杂对象不能作为一个完整的产品使用.比如汽车包括方向盘.车门.发动机 ...

  7. 当input中的内容改变时触发的事件

    当input中的内容改变时触发的事件 1 $('#id').bind('input propertychange', function() { //处理内容 } 循环js事件 $(document). ...

  8. POJ 3187 Backward Digit Sums (dfs,杨辉三角形性质)

    FJ and his cows enjoy playing a mental game. They write down the numbers from 1 to N (1 <= N < ...

  9. Cisco基础(六):配置目前网络环境、项目阶段练习

    一.配置目前网络环境 目标: 一家新创建的IT公司,公司位于北京有80多台服务器 目前网络环境使用技术,通过端口映射技术将web服务器发布给Internet: 三层交换:汇聚接入层交换机 默认路由:实 ...

  10. 【2019 Multi-University Training Contest 1】

    01:https://www.cnblogs.com/myx12345/p/11543105.html 02:https://www.cnblogs.com/myx12345/p/11439320.h ...