1.关于生命周期
1.1生命周期有哪些?发送请求是在created还是mounted
beforeCreate:创建之前(
el
、data
和message
都还是undefined
,不可用的)created:创建完毕(能读取到数据
data
的值,但是DOM
还没生成)beforeMount:挂载之前(生成
DOM
,但此时{{ message }}
还没有挂载data
中的数据)mounted:挂载完毕(
{{ message }}
已经成功挂载渲染data
的值)beforeUpdate:更新之前
updated:更新完毕
beforeDestroy:销毁之前
destroyed:销毁完毕
activated:
keep-alive
组件激活时调用deactivated:
keep-alive
组件停用时调用
注意:
activated
和deactivated
是比较特殊的两个钩子,需要keep-live
配合使用- 当引入
keep-alive
的时候,页面第一次进入,钩子的触发顺序created
=>mounted
=>activated
,退出时触发deactivated
。当再次进入(前进或者后退)时,只触发activated
。
如果我们的请求不需要获取/借助/依赖/改变DOM,这时请求可以放在Created
反之则可以放在Mounted里
1.2 一旦进入组件会执行哪些生命周期
beforeCreate
created
beforeMount
mounted
1.3父组件引入子组件生命周期的执行顺序是?
父:beforeCreate created beforeMount
子:beforeCreate created beforeMount mounted
父:mounted
1.4 为什么发送请求不在beforeCreate中?beforeCreate和created有什么区别
因为如果请求封装在methods中,在beforeCreate调用的时候,这个阶段时拿不到methods中的方法的所以不行。
beforeCreate中没有data
created中有data
2.关于组件
2.1 组件的通信方式
父子组件之间的通信
props
$emit/v-on
attrs/listeners
ref (http://t.csdn.cn/AGOIR)
.sync
v-model
children/parent
兄弟组件之间的通信
EventBus
Vuex
$parent
2.2 如何找到根组件
this.$root
2.3 slot
默认插槽、具名插槽、作用域插槽
默认插槽:
父组件
<template><div class="container"><!--默认插槽--><!--写在标签上的是父组件以props形式向子组件传递的属性,与插槽无关--><Category title="美食" :listDate="foods"><!--希望向子组件中插入的内容--><img src="img1.jpg"></Category></div>
</template><script>import Category from './components/Category'export default{name:'App',components:{Category}}
</script>
子组件
<template><div class="category"><slot></slot></div>
</template>
<script>export default{name:'Category'}
</script>
具名插槽
有时候会同时需要多个插槽,并将其渲染到不同的位置上,此时就需要使用具名插槽
父组件
<template><div class="container"><Category title="美食" :listDate="foods"><!--添加名称--><template v-slot:center><img src="img1.jpg"></template><!--添加名称--><template v-slot:footer><a href="www.baidu.com">百度</a></template></Category></div>
</template><script>import Category from './components/Category'export default{name:'App',components:{Category}}
</script>
子组件
<template><div class="category"><!--指定名称--><slot name="center"></slot><!--指定名称--><slot name="footer"></slot></div>
</template>
<script>export default{name:'Category'}
</script>
作用域插槽
当数据在组件的自身,而根据数据生成的结构需要组件的使用者来决定时,就要用作用域插槽
假设子组件
<current-user>
具有user对象数据,此时有如下代码
父组件
<current-user><template v-slot:default="ScopeData">{{ ScopeData.user.firstName }}</template>
</current-user>
子组件
<span><slot :user="user"></slot>
</span>
3.Vuex
3.1 对vuex的理解
Vuex实现了一个单向数据流,在全局拥有一个State存放数据,当组件要更改State中的数据时,必须通过Mutation进行,Mutation同时提供了订阅者模式供外部插件调用获取State数据的更新。而当所有异步操作(常见于调用后端接口异步获取更新数据)或批量的同步操作需要走Action,但Action也是无法直接修改State的,还是需要通过Mutation来修改State的数据。最后,根据State的变化,渲染到视图上。
3.2 vuex有哪些属性
有五种,分别是 State、 Getter、Mutations 、Actions、 Modules
- state => 基本数据(数据源存放地)
- getters => 从基本数据派生出来的数据
- mutations => 提交更改数据的方法,同步
- actions => 像一个装饰器,包裹mutations,使之可以异步。
- modules => 模块化Vuex
各模块在流程中的功能:
Vue Components:Vue组件。HTML页面上,负责接收用户操作等交互行为,执行dispatch方法触发对应action进行回应。
dispatch:操作行为触发方法,是唯一能执行action的方法。
actions:操作行为处理模块,由组件中的$store.dispatch('action 名称', data1)来触发。然后由commit()来触发mutation的调用 , 间接更新 state。可以定义异步函数,并在回调中提交mutation,就相当于异步更新了state中的字段
commit:状态改变提交操作方法。对mutation进行提交,是唯一能执行mutation的方法。
mutations:状态改变操作方法,由actions中的commit('mutation 名称')来触发。是Vuex修改state的唯一推荐方法。该方法只能进行同步操作,且方法名只能全局唯一。
state:state中存放页面共享的状态字段
getters:相当于当前模块state的计算属性
3.3 Vuex 为什么要分模块并且加命名空间
模块:由于使用单一状态树,应用的所有状态会集中到一个比较大的对象。当应用变得非常复杂时,store 对象就有可能变得相当臃肿。为了解决以上问题,Vuex 允许我们将 store 分割成模块(module)。每个模块拥有自己的 state、mutation、action、getter、甚至是嵌套子模块。
3.4 Vuex和单纯的全局对象有什么区别?
Vuex 的状态存储是响应式的。当 Vue 组件从 store 中读取状态的时候,若 store 中的状态发生变化,那么相应的组件也会相应地得到高效更新。
不能直接改变 store 中的状态。改变 store 中的状态的唯一途径就是显式地提交 (commit) mutation。这样使得我们可以方便地跟踪每一个状态的变化,从而让我们能够实现一些工具帮助我们更好地了解我们的应用。
3.5 为什么 Vuex 的 mutation 中不能做异步操作?
每个mutation执行完成后都会对应到一个新的状态变更,这样devtools就可以打个快照存下来,然后就可以实现 time-travel 了。如果mutation支持异步操作,就没有办法知道状态是何时更新的,无法很好的进行状态的追踪,给调试带来困难。
action 可以进行一系列的异步操作,并且通过提交 mutation 来记录 action 产生的副作用(即状态变更)
3.6 Vuex中 action 和 mutation 的区别
mutation中的操作是一系列的同步函数,用于修改state中的变量的的状态。它会接受 state 作为第一个参数,第二个参数是参数。
const store = new Vuex.Store({state: {count: 1},mutations: {increment (state) {state.count++ // 变更状态}}
})
当触发一个类型为 increment 的 mutation 时,需要调用此函数:
increment: function() {this.$store.commit('increment')
}
而Action类似于mutation,不同点在于:
- Action 可以包含任意异步操作。
- Action 提交的是 mutation,而不是直接变更状态。
const store = new Vuex.Store({state: {count: 0},mutations: {increment (state) {state.count++}},actions: {increment (context) {context.commit('increment')}}
})
Action 函数接受一个与 store 实例具有相同方法和属性的 context 对象,因此你可以调用 context.commit 提交一个 mutation,或者通过 context.state 和 context.getters 来获取 state 和 getters。
在Vue组件中, 如果我们调用action中的方法, 那么就需要使用dispatch
methods: {increment() {this.$store.dispatch('increment')}
}
3.7 vuex的持久化存储
Vuex是一个仓库,是vue的状态管理工具,存放公共数据,任何组件都可以使用vuex里的公共数据。Vuex提供了插件系统,允许我们使用 vuex-persistedstate插件,将Vuex的状态持久化到本地存储中,解决页面刷新或重新打开应用时状态丢失的问题;
方法一: 通过手写函数和plugins,实现状态、数据持久化话;
新建pluginPersist.js文件,并导出存储函数
/*** * @param {状态、数据持久化} store */
export default function (store) {// console.log(store);// 存const KEY = 'VUEX:STATE';//这里表示 页面关闭 或 刷新 时存储window.addEventListener("beforeunload", () => {localStorage.setItem(KEY, JSON.stringify(store.state))})// 取try {const state = JSON.parse(localStorage.getItem(KEY));if (state) {store.replaceState(state);}} catch (err) {console.log(err);}
}
在store中,在plugins里引入挂载使用;plugins插件中的函数会在创建仓库时执行,插件的本质就是一个函数
import Vue from 'vue'
import Vuex from 'vuex'
import pluginPersist from "./pluginPersist"Vue.use(Vuex)const store = new Vuex.Store({state: { // ...状态、数据 }, mutations: { // ...修改状态、数据}, actions: { // ...动作函数 }, getters: { // ...计算属性}, modules: {// ...模块化},//这里使用plugins: [pluginPersist],})export default store;
方法二: 通过手写db对象方法,实现数据、状态持久化;
新建localStorage.js文件,创建db对象,然后导出db方法
var localStorage = window.localStorage;
const db = {/** * 更新状态 */save(key, value) {localStorage.setItem(key, JSON.stringify(value));},/** * 获取状态,如果有状态值,获取最新状态值;如果没有,获取默认值 */get(key, getSaveVal = null) {try {return JSON.parse(localStorage.getItem(key)) || getSaveVal;} catch (err) {console.log(err);}},/** * 移除状态 */remove(key) {localStorage.removeItem(key);},/** * 清空状态 */clear() {localStorage.clear();}
};
export default db;
在store中引入使用
import Vue from 'vue'
import Vuex from 'vuex'
import db from './localStorage';Vue.use(Vuex)const store = new Vuex.Store({state: {// 初始化时 默认获取state1: db.get('STATE1') || null,},mutations: {SET_STATE1: (state, value) => {state.state1++//调用SET_STATE1方法时 这里存储db.save('STATE1', state.state1);},},actions: { // 动作函数 }, getters: { // 计算属性}, modules: {// 模块化},// 插件plugins: [],})export default store
方法三 :通过vue插件vuex-persistedstate 或 vuex-plugin-persistedstate实现数据、状态持久化;
安装依赖
npm install vuex-persistedstate --save
//或者
cnpm install vuex-persistedstate --save
//或者
yarn add vuex-persistedstate--save是安装在生产环境,开发和生产都需要用到//查看插件的依赖项
npm ls vuex-persistedstate
vuex-persistedstate 和 vuex-plugin-persistedstate 是同一个插件的不同引用方式,它们都是用来持久化 Vuex 状态管理的插件,可以将 Vuex 中的状态保存到本地存储(如 localStorage 或 sessionStorage)中,以便在刷新页面或重新打开应用时恢复这些状态;persist目前已经弃用;
使用
import Vue from 'vue';
import Vuex from 'vuex';
import createPersistedState from 'vuex-persistedstate'; Vue.use(Vuex); export default new Vuex.Store({ state: { // ...你的状态定义 }, mutations: { // ...你的变更函数定义 }, actions: { // ...你的动作函数定义 }, getters: { // ...你的计算属性定义 }, modules: {// ...模块化},plugins: [ createPersistedState({ storage: window.localStorage, // 或者使用 sessionStorage }), ],
});
4. 路由
4.1 路由的模式和区别
未完待续.....