目录
一、Vuex状态管理
1. vue组件间通信方式
父组件给子组件传值
子组件获取父组件传的值:props:{ fontSize: {...}} / props: ['fontSize']
provide: ['fontSize']
子组件给父组件传值
this.$emit(handler, option)
inject: ['fontSize']
不相关组件之间的传值
eventBus
// eventBus.js
import Vue from 'Vue'
export default new Vue()
// a.vue
import bus from './eventBis.js'
bus.$emit('handlerChange', value)
b.vue
import bus from './eventBis.js'
bus.$on('handlerChange', value => {...})
$root $parent $childern $refs
ref在标签上 获取的是DOM, 在组件上是组件实例
<child ref="child"></child>
// 获取组件上的方法或值
this.$refs.child.xxx
vuex存储库
2. vuex核心概念及基本使用
- vuex是专门为vue.js设计的状态管理库,是JS库
- vuex采用集中式的方式存储需要共享的状态
- vuex的作用是进行状态管理,解决复杂组件之间的通信
- vuex集成到了devtools中,提供了time-travel时光旅行历史回滚功能
// Store State Getter Mutation Action Modulev
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
count: 0,
msg: 'learn vuex'
},
getters: {
reverseMsg(state) {
return state.msg.split(' ').reverse().join(' ')
}
},
// 同步执行
mutations:{
increate(state, payload){
state.count += payload
}
},
// 可执行异步任务
actions:{
increateAsync({ commit }, payload) {
setTimeout(()=>{
commit('increate', payload)
},1000)
}
},
modules:{
product // 另一个包含state actions mutations getters的store
}
})
// 使用
$store.state.count
$store.getters.reverseMsg
$store.commit('increate', 2)
$store.dispatch('increateAsync', 2)
// 或
import { mapState, mapGetters, mapMutations, mapActions } from 'Vuex'
// state getters的使用
computed:{
...mapState(['count'])
...mapGetters(['reverseMsg'])
}
// 取别名
computed:{
...mapState({ num:'count'})
}
// mutations actions的使用
methods:{
...mapMutations(['increate']) // 模板中直接使用increate(2)
...mapActions(['increateAsync'])
}
// 使用module模块里的store
this.$store.state.product.xxx
// 提交mutations是一样的 this.$store.commit('handle', xxx)
//开启命名空间 nameSpace:true 区分不同模块的行为
...mapState('product', ['xxx'])
...mapMutations('product', ['xxx'])
3. 模拟实现vuex
// myvuex/index.js
let _vue = null;
class Store{
constructor(options) {
const { state = {}, getters = {}, mutations ={}, actions = {}} = options;
this.state = _Vue.observable(state);
this.getters = Object.create(null);
Object.keys(getters).forEach(key => {
Object.defineProperty(this.getters, key, {
get: () => getters[key](state)
})
})
this._mutations = mutations
this._actions = actions
}
commit(type, payload) {
this._mutations[type](this.state, payload)
}
dispatch(type, payload) {
this._actions[type](this, payload)
}
}
function install(Vue) {
_Vue = Vue
_vue.mixin({
beforeCreate() {
if (this.$options.store) {
_Vue.prototype.$store = this.$options.store
}
}
})
}
export default {
Store,
install
}
二、服务端渲染基础
1. SPA单页面应用的优缺点
优点:
- 用户体验好
- 开发效率高
- 渲染性能好
- 可维护性好
缺点:
- 首屏渲染时间长
- 不利于SEO(搜索引擎)
2. 传统的服务端渲染(SSR)
缺点:
- 前后端代码混合
- 服务端压力大
- 体验不够好 页面要整体刷新
3. 客户端渲染(CSR)
缺点:
- 首屏渲染时间长
- 不利于SEO(搜索引擎)
4. 同构渲染
- 在服务端执行一次,用于实现服务端渲染(首屏直出)
- 在客户端再执行一次,用户接管页面交互
注意事项:
- 不能在服务端渲染期间操作DOM
- 一些扩展库可能需要特殊的处理才能在服务端渲染应用中运行
- 某些操作代码需要区分运行环境
- 浏览器特定的代码只能在某些生命周期钩子函数中使用
与客户端渲染在构建和部署上的区别
三、NuxtJs
一个基于Vue.js生态的第三方开源服务端渲染应用框架
可以轻松的使用Vue技术栈构建同构应用
通过对客户端/服务端基础架构的抽象组织,Nuxt.js 主要关注的是应用的 UI 渲染。
可以基于它初始化新项目的基础结构代码,或者在已有 Node.js 项目中使用 Nuxt.js。
1. 创建初始化项目
npm init -y
npm install nuxt
npm run nuxt
// nuxt框架
yarn create nuxt-app <项目名>
2. 路由
路由的基础使用
//nuxt 会根据pages目录下的文件自动生成路由
// nuxt-link组件
<nuxt-link to=""></nuxt-link>
<router-link to=""></router-link>
// 编程式导航
this.$router.push('/')
// 动态路由
// 文件名 user/_id.vue 以下划线开头
this.$route.params.id
// 嵌套路由
// 添加一个Vue文件,同时添加一个与该文件同名的目录存放子视图组件
// 在父组件中使用<nuxt-child></nuxt-child>占位
//比如pages/users/_id.vue|index.vue pages/user.vue(这就是父组件)
//自定义路由配置
// nuxt.config.js
module.exports = {
router: {
base: '/app',
extendRoutes(routes, resolve) {
routes.push({
name: 'custom',
path: '*',
component: resolve(__dirname, 'pages/404.vue')
})
}
}
}
//之后访问路径都会以/app开头
校验动态路由参数的有效性validate
validate({ params, query }) {
return true // 如果参数有效
return false // 参数无效,Nuxt.js 停止渲染当前页面并显示错误页面
}
watchQuery监听参数字符串
参数字符串更改并在更改时执行组件方法 (asyncData, fetch, validate, layout, ...)
默认不使用
export default {
watchQuery: ['page']
}
3. 视图
模板
<!-- 在根目录下创建app.html -->
<!DOCTYPE html>
<html {{ HTML_ATTRS }}>
<head {{ HEAD_ATTRS }}>
{{ HEAD }}
</head>
<body {{ BODY_ATTRS }}>
<!-- 渲染的内容 -->
{{ APP }}
</body>
</html>
布局
根目录下layout/default.vue文件夹 文件中需要<nuxt/>用于显示页面内容
当需要问一个.vue文件指定父组件 可以使用 layout:'xxx' // xxx 是layout下面的组件
4. asyncData异步数据
asyncData的使用
export default {
name: 'xxx',
async asyncData() {
// 根据接口获取后端数据然后return出去 return 出去的数据会放在data中
}
}
- 服务端渲染期间 渲染到客户端前 客户端路由导航前执行
- 只能在页面组件(pages下的页面)中使用
- 没有this 组件渲染前调用的
上下文对象
async asyncData(context) {
// 根据接口获取后端数据然后return出去 return 出去的数据会放在data中
// context: 上下文中含有 params
}
5. middleware 中间件
相当于路由守卫 判断是否有权限
// pages/secret.vue
<template>
<h1>Secret page</h1>
</template>
<script>
export default {
middleware: 'authenticated'
}
</script>
//middleware/authenticated.js
export default function ({ store, redirect }) {
// If the user is not authenticated
if (!store.state.authenticated) {
return redirect('/login')
}
}