文章目录
Vue框架
上层框架 只关注数据驱动 借鉴MVVM模式
MVVM模式
- M Model层 数据模型层
- V View 视图层
- VM ViewModel层 视图数据层
M层发生变化VM层中得Data Bindings监听到M层变换通知V层及时更新
V层发生变化VM层中得DOM Listeners监听到V层变化通知M层及时更新
生命周期 **************************
从vue实例创建到虚拟dom产生到数据绑定数据监听到销毁得过程
- 实例创建阶段
- beforeCreate 实例创建前
初始化默认事件和默认生命周期,此时实例还没创建完成,无法访问data数据和methods方法 - created 实例创建完成
初始化数据注入和数据监听,此时实例创建完成,可以访问data数据和methods方法
最早得异步请求
- beforeCreate 实例创建前
- 实例挂载阶段
- beforeMount 实例与模板绑定之前 完成模板编译
查看有无el选项,有查看有无template选项,没有template选项会把el外部html作为模板编译,
有el选项,有template选项,将template作为模板使用render函数编译。如果没有el选项,使用
实例方法$mount()完成模板编译
此时模板与实例还未绑定 无法访问dom元素 - mounted 实例与模板绑定完成 创建$el代替el选项
此时可以访问dom元素
- beforeMount 实例与模板绑定之前 完成模板编译
- 实例更新阶段 只要数据发生改变就会触发生命周期
- beforeUpdate 实例更新前
此时可以获取到最新得数据 但是使用到数据dom元素还未更新完成 旧dom元素 - updated
此时可以获取到最新得数据 使用到数据dom元素更新完成 新dom元素
- beforeUpdate 实例更新前
- 实例销毁阶段 $destroy销毁组件
- beforeDestroy 实例销毁前 此时可以修改数据和方法
- destroyed 实例销毁完成 此时移除监听器、子组件和事件监听,修改数据和方法失败,但是可以访问
此外还有三个
- activited 组件激活
- deactivated 组件未激活
- errorcaptured 错误调用
事件修饰符
.stop 阻止事件冒泡
. prevent 阻止默认事件的触发
. capture 捕获事件
. self 仅当前元素是event.target触发
. once 执行一次事件
. passive 事件的默认行为立即执行,无需等待事件回调执行完毕。
指令总结
绑定事件 v-on:事件类型=“事件处理程序” (@事件类型=“程序”)
绑定变量 v-bind:变量名=“值名” (:变量名=“值名”)
双向绑定 v-model = “ ” (一般用于表单)
模板语法 {{ }} v-text=“ 不会解析代码” v-html=“ 会解析代码” ref=“ 获取dom元素 ”
执行一次性插值 v-once(后续数据发生变化 插值处数据不发生改变)
条件渲染 v-if、v-else-if、v-else
显示与隐藏 v-show
循环 v-for=“(item,index) in/of items” :key=“id”
v-for=“(value,key,index) in obj” :key=“id”
style动态绑定 v-bind:style= “ ”
class动态绑定 v-bind:class=“ ”
具名插槽 v-slot:插槽名
自定义指令 directive (与创建组件相同)
自定义指令 v-xxx
全局注册
Vue.directive('指令名称',{
//当被绑定元素插入到父节点调用
inserted(el,binding,vnode,oldNode){
el--------->绑定指令dom元素
binding---->元素数据 value
vnode ----->虚拟节点 dom对象内存中数据表示
oldNode---->旧节点
},
//执行一次性初始化设置
bind(el,binding,vnode,oldNode){ }
//组件vnode更新触发
update(el,binding,vnode,oldNode){ }
})
局部注册
directives:{
myshow:{
inserted(){
},
bind(){
},
update(){}
}
}
模板语法
<body>
<!-- 视图 -->
<div id="app">
1.Mustache 文本插值 只会把变量当作普通文本进行渲染 不会解析html代码
{{msg}} <!-- hello vue2 -->
<div>{{content}}</div> <!-- <p>我是段落标签<a href='https://www.baaidu.com'>百度一下</a></p> -->
<div v-text="content"></div> <!-- <p>我是段落标签<a href='https://www.baaidu.com'>百度一下</a></p> -->
2.v-html 解析html代码片段
<div v-html="content"></div> <!-- 我是段落标签 百度一下 -->
3.绑定变量 v-bind: 简写为 :
<div title="{{title}}">我是一个div</div> <!-- 鼠标放上显示:{{title}}-->
<div v-bind:title="title">我是一个div</div> <!-- 鼠标放上显示:我是div的提示说明-->
<div :title="title">我是一个div</div> <!-- 鼠标放上显示:我是div的提示说明-->
4.js表达式 双花括号内部可以直接使用js表达式
{{str.split(' ').reverse().join(' ')}}
{{Boolean(msg)}}
{{3>2?'YES':'NO'}}
<!-- world hello true YES -->
</div>
<script>
//创建VEU得实例
let vm=new Vue({
//绑定模板
el:'#app',
//数据模型 存放vue变量
data:{
msg:'hello vue2',
str:'hello world',
title:"我是div的提示说明",
content:"<p>我是段落标签<a href='https://www.baaidu.com'>百度一下</a></p>"
},
//函数和事件处理程序
methods:{
},
});
</script>
事件机制
使用v-on绑定事件 v-on:事件类型 简写为@
每一个事件处理程序都有一个事件对象
div @click='handler("hello",12,$event)'
handler(a,b,c){
console.log(event,a,b,c,'c就是事件对象')
}
表单双向数据绑定 v-model
监听用户输入事件以更新数据 创建双向数据绑定
v-model修饰符:
lazy 输入事件input事件 change事件 失焦或者按下回车
number 将输入框双向绑定得数据设置为number类型
trim 过滤绑定数据前后空格
双向数据绑定实现Object.defineProperty()
<p></p>
<input type='text'>
let obj = {
name:""
}
input.oninput = function(){
obj.name = this.value;//获取用户输入框输入得内容
}
Object.defineProperty(obj,'name',{
get(){
return obj.name
},
set(newValue){
newValue --->this.value;
p.innerHTML = newValue;
}
})
v-if和v-show区别**********************************
- v-if 对应的是组件创建和销毁,满足条件对应的组件创建,不满足则销毁。
v-if是惰性的,如果初始条件不满足,dom元素就不会被渲染 - v-show无论初始条件满不满足,都会渲染到模板中,对应的是css属性显示与隐藏,满足显示元素,不满足条件隐藏元素
- v-if :引起重排,有更高切换开销,如果条件很少改变情况可以使用v-if指令渲染;
v-show :引起重绘,有更高初始渲染,用于频繁切换
style绑定 与class绑定
内联样式绑定
style='{color:currentColor}'
style='styleObj'
style='[styleObj,styleObj1]'
styleObj:{
color:"red",
fontSize:28
}
:class='type==="xxx"?"current":""'
:class='{active:isActive}'
:class='{active:isActive,error:hasError}'
:class='[{active:isActive,error:hasError},{class:true}]'
组件注册
可复用的vue实例,封装了重复的代码,可以多次调用组件/重复使用。
全局注册
Vue.component('组件名称',{
data(){ return { } },
methods:{ },
...
template:` <div>组件模板</div> `
})
局部注册
components:{
'组件名称':组件配置项{ }
}
动态组件
component标签动态切换组件,使用is属性切换组件
使用component切换组件,组件会不停的创建和销毁,如果想在第一次创建时候缓存组件,可以
使用keep-alive包裹
- 与keep-alive相关生命周期:
- activated 使用keep-alive缓存的组件激活(进入)的时候触发
- deactivated 使用keep-alive缓存的组件失活(离开)的时候触发
- errorCaptured 捕获后代组件错误时触发
- error(错误对象)
- vm(发生错误的组件)
- info(错误提示字符串)
<body>
<div id="app">
<!-- 使用component动态切换组件 is属性 组件名称 -->
<!-- <component v-bind:is="current"></component> -->
<!-- keep-alive作用:希望第一次创建组件时候被缓存 后续切换不会重新创建和销毁 -->
<!-- <keep-alive> -->
<component v-bind:is="current"></component>
<!-- </keep-alive> -->
<button @click="current='my-person'">加载个人组件</button>
<button @click="current='my-company'">加载企业组件</button>
</div>
<script>
let myPerson = {
template: ` <div>个人组件</div> `,
created() { console.log('个人组件创建') },
destroyed() { console.log('个人组件被销毁')}
};
// 声明后代组件
let companyChild = { template:` <div>{{subMsg}}</div> ` };
let myCompany = {
components:{ 'company-child':companyChild },
template: ` <div>企业组件<company-child></company-child></div> `,
created() {console.log('企业组件创建') },
destroyed() { console.log('企业组件被销毁')},
activated(){console.log('被keep-alive缓存的组件激活的时候触发 进入组件时候触发')},
deactivated(){ console.log('被keep-alive缓存的组件失活的时候触发 离开组件时候触发')},
// 捕获后代组件发生错误时触发
errorCaptured(err, vm, info){
console.log(err,'发生错误')
console.log(vm,'发生错误组件')
console.log(info,'字符串信息提示')
},
}
new Vue({
el: "#app",
components: {
'my-person': myPerson,
'my-company': myCompany
},
data: {
current: 'my-person'
},
methods: {
}
})
</script>
</body>
key作用:
vue采用得是diff算法,会高效复用组件,当组件相似的时候,一般往往是复用而不是重新创建,这样渲染效率会变得低下。
如果不希望被复用,就可以给组件设置一个唯一标识key,告诉vue是不希望被复用得节点
组件data为什么是一个函数不是一个对象
(如果是对象,引用地址一样,改一即该三)
因为组件实例是可以被复用得,如果data是一个对象就会全局可见,只要其中一个使用到该组件得组件修改了数据,剩下使用到该组件得组件数据也会被修改。data只能返回一个函数返回一个对象,对象数据只在当前组件内可见!
- 组件是一个可复用的实例,当你引用一个组件的时候,组件里的data是一个普通的对象,所有用到这个组件的都引用的同一个data,就会造成数据污染。
- 不使用return包裹的数据会在项目的全局可见,会造成变量污染;
使用return包裹后数据中变量只在当前组件中生效,不会影响其他组件。- 当一个组件被定义, data 必须声明为返回一个初始数据对象的函数,因为组件可能被用来创建多个实例。如果 data 仍然是一个纯粹的对象,则所有的实例将共享引用同一个数据对象!通过提供 data 函数,每次创建一个新实例后,我们能够调用 data 函数,从而返回初始数据的一个全新副本数据对象。
计算属性
computed:{
reverse(){
return this.msg.xxx()
},
fullName:{
get(){ },
set(){ }
}
}
{{reverse}}
- 对data中数据进行逻辑处理返回一个响应式数据(基于响应式依赖(data),只要响应式依赖不发生改变,计算属性就不会重新计算,多次调用计算属性会返回之前计算得结果)
- 有缓存性
- 计算属性默认只提供getter,只可读,不允许修改,
- 想要修改计算属性,需要提供setter函数。
处理响应式依赖选项,对data中数据进行处理再返回基于data响应式数据的依赖,计算属性会在第一次把计算结果进行缓存,如果响应式依赖没有发生改变,再次调用计算属性会立即返回 第一次得结果,而不会重新计算。计算属性默认只提供getter函数,只能进行读取,如果修改计算属性, 提供setter函数。
侦听器
只有监听数据发生改变才会触发监听器
watch:{
监听基本数据类型
page(n,o){
console.log(n,o,新数据,原始数据)
}
监听引用数据类型
params:{
handler(n,o){
this.getArticle();
},
//开启深度监听
deep:true
}
}
计算属性与methods方法区别?
- 计算属性具有缓存性,data数据不发生改变多次调用会返回第一次缓存得结果
- methods无缓存性,调用一次方法执行一次
- methods可以处理异步操作,计算属性一般不用于异步操作
计算属性和watch区别?
- 计算属性具有缓存性,响应式依赖不变,计算属性就不会重新计算,而是会返回之前得计算结果。
- watch无缓存性,只有数据发生改变,侦听器才会执行。
- watch一般用于异步操作(监听分页)或者开销较大操作
- 计算属性一般不用于异步操作,只提供getter,默认可读,设置setter就可修改。
组件通信/传值方式?*******************************************
vuex也可以实现传值
1.父组件给子组件传值:
- props
- 在父组件的子组件标签中写入父组件传递的数据 向下传递prop
- 在子组件内声明props选项接收父组件传递的数据
props:[‘’,‘’,‘’] 或props:{ , , ,} (这个是对传递的数据进行类型验证)- provide与 inject
- 父组件使用provide提供传递数据或者方法
provide(){ return{ 变量名:值} }- 子组件使用 inject:[‘变量名’] 注入传递的数据或者方法
- 定义事件总线导出实例对象
$emit 和 $ on
- 新建event.js
import Vue from ‘vue’;
export default new Vue();- 在父组件新建方法中使用$emit发射自定义事件同时传递参数
import Bus from ‘./event.js’- 在子组件新建created(){}中使用.$ on监听自定义事件同时接收参数
import Bus from ‘./event.js’
Bus.$on(‘自定义事件名称’,(a,b)=>{ })
2、子组件给父组件传值:
- &emit
- 发射自定义事件(在子组件中新建方法)给父组件同时传递数据
this.$emit(‘自定义事件名’,传递数据1,传递数据2);- 在父组件模板中(在子组件标签上)声明自定义事件
<子组件标签 @自定义事件名=‘事件处理程序’> </子组件>
事件处理程序(接收子组件传递的数据1,数据2){ }- 作用域插槽
3、兄弟组件传值/通信
- 同父传子方法3
定义事件总线导出实例对象
$emit 和 $ on
- 定义事件总线 新建xxx.js
import Vue from ‘vue’;
export default new Vue();- 在一个兄弟组件中引入事件总线
import Bus from ‘./event.js’
使用Bus.$emit(‘自定义事件名称’,传递的数据)- 在另一个兄弟组件中引入事件总线
import Bus from ‘./event.js’
使用Bus. $on(‘emit发射自定义事件名称’,(a,b)=>{})
监听发射自定义事件 同时接收数据
4、祖先后代组件传值/通信
- 同父传子方法2
- 祖先组件使用provide提供数据
- 后代组件使用inject注入数据
props验证
对父组件传值的校验
props:{
propA:String,
propB:[String,Number,Boolean],
propC:{
required:true,
type:String
},
//基本数据类型
propD:{
type:Number,
default:10
},
//引用数据类型
propE:{
type:Array,
default(){
return [1,2,3,4]
}
},
//自定义校验器
propF:{
validator(val){
return ['success','warning'].includes(val)
return true
}
}
}
单向数据流
数据从上层流向下层,上层(父组件)修改数据子组件数据也会被修改,但是反过来不可以。
(父组件会修改自己和子组件,而子组件只能改自己)
axios
基于promise的http库,可以运行在浏览器和nodejs。
特性:
- 运行在浏览器和nodejs
- 基于promise(可以使用promise实例方法)
- 可以对请求和响应拦截处理
- 运行在浏览器创建XMLHttpRequests
- 运行在nodejs创建http请求
如何使用axios发起请求?
- 安装
cnpm/npm install axios -S
bootcdn
axios({
请求路径 url:“”, //必需参数
请求方式 method:“”, (axios默认发起的是get请求)
请求头 headers:{},
url参数 params:{},
请求体参数 data:{},
超时处理 timeout:2000,
基础路径 baseURL:‘’
})
- 方法别名/快捷方法:
- axios.get(url,请求配置项)
无参: axios.get(url)
有参: axios.get(url,{ params:{参} })- axios.post(url,data,请求配置项)
axios发起post请求默认数据格式是json数据格式—登录
axios发起表单格式post请求,需要设置请求头Content-type:application/x-www-form-urlencoded
3.全局默认值
- axios.defaults.baseURL = ‘’;
- axios.defaults.headers[‘Auth’]=‘token’;
- axios.defaults.headers.post[‘Content-Type’]=‘application/x-www-form-urlencoded’
axios二次封装
创建实例
const instance = axios.create({
baseURL:"",
timeout:5000,
.....
})
请求拦截器:对请求的数据进行认证
let id = axios.interceptors.request.use(config=>{
if(token){
config.headers['Authorization']='adasfdaff'
}
return config
},error=>{
return Promise.reject(error)
})
响应拦截器:对响应的数据进行拦截,处理
let id = axios.interceptors.response.use(response=>{
return response.data
},error=>{
return Promise.reject(error)
});
封装get 、post 、postJSON
export function get(url,params){
return axios.get(url,{
params
})
}
export function postJSON(url,data){
return axios.post(url,data)
}
export function post(url,data){
return axios.post(url,Qs.stringify(data))
}
//导出创建的实例
export default instance
移除拦截器
axios.interceptors.request.eject(id)
axios.interceptors.response.eject(id)
插槽 slot
父组件传递模板给子组件,子组件使用插槽声明slot元素承载分发内容出口。
- 默认插槽:父组件提供给子组件模板,默认会填充到默认插槽中
< slot name=‘default’></ slot> - 具名插槽:父组件提供了具体的模板,填充到具名插槽中
< template v-slot:header></ template>
< slot name=‘header’></ slot> - 作用域插槽:父组件作用域使用子组件数据
-
- 在子组件默认插槽中动态绑定插槽prop
< slot v-bind:user=‘user’>
- 在子组件默认插槽中动态绑定插槽prop
-
- 在父组件模板中使用v-slot='插槽prop’接收子组件数据
< template v-slot=‘scope’>
{{scope.user.xxxx}}
</ template>
- 在父组件模板中使用v-slot='插槽prop’接收子组件数据
-
render函数
需要js完全编程能力,比模板更接近编译器,编译模板
render(createElement){
return createElement(标签名称,{标签属性},子节点数组)
}
render(createElement){
return createElement(标签名称,{},[this.$slots.default,...lis])
}
过滤器 filter
格式化文本,时间都可以使用过滤器,使用在双花括号内部,使用在v-bind表达式
全局注册过滤器
Vue.filter('过滤器名称',function(val){
val---->需要格式化文本
return val.toUpperCase();
})
局部注册过滤器
filters:{
'fmtDate'(val){
return moment(val).format('YYYY-MM-DD')
}
}
过滤器使用
{{msg | fmtDate}}
<div v-bind:title='title | fmtDate'></div>
串联使用
{{msg | filterA | filterB}}
过滤器js函数,可以传递参数
{{msg | filterA('hello',{name:"terry"})}}
插件 install 、 use
添加Vue的全局功能,开发插件必须暴露install方法
开发插件:
let myPlugin = {
install(Vue,options){
Vue.Method = function(){
};
Vue.directive('focus',{
});
Vue.filter('filterA',function(val){
});
Vue.prototype.$message = function(){
}
}
}
使用插件(在new Vue之前)
Vue.use(myPlugin)
混入 mixin
来分发Vue组件中可复用的功能,一个混入对象可以包含任意组件选项。
当组件使用混入对象时,所有混入对象的选项将被“混合”进入该组件本身的选项。
可以对数据和对象选项进行混入,接收组件任意选项。
全局混入:
Vue.mixin({
data(){
return {
}
},
methods:{
},
computed:{
}
});
let mixin = {
}
局部混入:
mixins:[mixin]
全局混入对象会影响到每一个组件,谨慎使用。
混入规则:
- data选项会进行合并,如果data数据发生冲突,会保留组件内的数据。
- ==生命周期(钩子函数)==会被合并到一个数组并依次调用,混入对象的生命周期先调用。
- 值为对象选项(methods,computed,watch,directive)也会合并到一个对象中,如果对象
键冲突保留组件内的键值对。
路由机制
通过路由加载组件的方式,主要处理单页面应用程序。
let myA = {};
let myB = {};
1.声明路由对象数组
const routes = [
路由所要加载组件---组件所对应的路由
{
path:"/myA",
component:myA
},
{
path:"/myB",
component:myB,
给路由设置名称
name:'myB',
重定向
redirect:'/other',{name:''}
给路由设置别名
alias:'/bb'
}
]
2.创建路由器实例对象
const router = new VueRouter({
routes:routes,
路由模式
mode:''
});
3.将路由器实例注册vue根实例
new Vue({
router
})
4.通过router-link标签访问组件
<router-link to='/myA'>A组件</router-link>
路由出口匹配
<router-view></router-view>
嵌套路由—>子路由
{
path:'/user',
component:User,
children:[
// 存放子路由对象
{ path:"childA" },
{ path:"childB" },
{ path:"childC" }
]
}
动态路由匹配
不同用户加载同一个组件,通过动态路径参数实现动态路由匹配。
< user>用户组件–{{id}}–{{username}}</ user>
{ path:‘/user/:id/:username’ }
响应路由参数变化?监听路由url地址栏变化***************************
1.使用watch监听路由对象
watch:{
$route(to,from){
to--->即将进入的路由params对象,可以获取到最新的路由参数
to.params存放着最新动态路径参数
from--->正在离开的路由
}
}
2.使用组件内导航守卫 beforeRouteUpdate 组件更新触发
beforeRouteUpdate(to,from,next){
to--->即将进入的路由
to.params存放着最新动态路径参数
from--->正在离开的路由
}
- 注意:使用created钩子获取路由对象参数只能获取到最初进入组件内路由的参数(因为只执行一次))
编程式导航进行页面跳转
$router.push() 会在浏览器产生一条历史记录
$router.replace() 不会在浏览器产生历史记录
$router.go(num) 前进或者后退几个页面
window.open();
location.assign(); push相似 会在浏览器产生一条历史记录
location.replace(); 页面替换 不会在浏览器产生历史记录
编程式导航传参***********************
name params 一次性数据携带 参数不会拼接在地址栏 刷新页面数据会丢失
path query 刷新页面数据不会丢失 参数拼接在地址栏
name query 刷新页面数据不会丢失 参数拼接在地址栏
路由模式 hash history 区别?************************
- hash会在地址栏拼接#,路由路径会拼接在#后面,
history地址栏正常 - hash原理是利用hashchange事件,可以通过newURL获取最新的路径,通过oldURL获取原始路径
history原理是利用history对象中的一些api,pushState,replaceState,go,back,forward方法 - hash刷新页面会重新加载路由对应的组件,不会对后端产生影响
history刷新页面会重新请求服务器,一般报错404。 - hash支持低版本的浏览器
history不支持低版本浏览器,利用h5新增api pushState方法
导航守卫
- 全局守卫
-
全局前置守卫:用户身份验证,做路由拦截(判断去的路由是否正确,是则继续向下,否则去正确的路由,可代替重定向)
router.beforeEach((to,from,next)=>{ next(); }) -
全局后置守卫:(不接受next(),也不改变导航本身,没大用)
router.afterEach((to,from)=>{ })to---->即将进入的路由
form—>正在离开的路由
next() 拦截路由是否继续向下执行
-
- 路由独享守卫:进入该路由时候触发,做路由拦截
- beforeEnter(to,from,next){ next();}
- 组件内导航守卫
三者区别:this指向获取组件实例- beforeRouterEnter(to,from,next){ }
进入组件时候触发,next((vm)=>{ vm---->组件实例 })
this指向windows全局对象 ,此时无法获取组件实例 - beforeRouteUpdate(to,from,next){ }
路由发生改变 , 但是复用该组件时候触发 /user/1/terry
this指向组件实例(因为被创建了实例) - beforeRouteLeave(to,from,next){}
离开路由时候触发
this指向组件实例
- beforeRouterEnter(to,from,next){ }
vuex*****************************
状态管理模式 ,维护公共状态的大型项目
A组件中分发工作(发起异步请求)—>获取数据—>提交突变(将数据提交给突变 )
通过突变修改状态 其他页面就可以渲染数据
let vuex = {
state:{}, 类似data 存储状态/数据
getters:{}, 类似于computed 对state处理后再进行返回
mutations:{}, 突变--->同步操作 修改state唯一一种方式
actions:{}, 动作--->异步操作 获取数据后提交给突变
modules:{} 分模块仓库
}
辅助函数
<script src="https://cdn.jsdelivr.net/npm/vue@2.7.14/dist/vue.js"></script>
<script src="https://cdn.bootcdn.net/ajax/libs/vuex/3.6.2/vuex.js"></script>
</head>
<body>
<div id="app">
<!-- 获取状态 $store.state/getters,
没有辅助函数的写法:
{{$store.state.public}}
{{$store.getters.Upper}}
{{$store.state.token}}
<button @click="$store.commit('SET_TOKEN','ejhwksdfdskjfhsdkhgkasdjflas')">提交突变</button>
<button @click="$store.dispatch('login',{username:'admin1',password:123321})">分发动作</button>
-->
<!-- 若为辅助函数的写法 -->
{{public}}
{{token}}
<button @click="SET_TOKEN('假的token')">提交突变</button>
<button @click="login({username:'admin1',password:123321})">分发动作</button>
</div>
<script>
// 引入辅助函数从Vuex中
let {mapState,mapGetters,mapActions,mapMutations} = Vuex;
// 1.声明状态机配置项
let storeConfig = {
//类似于data 存储公共状态 存储数据
state:{
public:'hello vuex',
token:""
},
// 类似于计算属性 对state中数据进行处理然后再返回
getters:{
Upper(state){
return state.public.toUpperCase();
}
},
// 突变 同步操作 修改state中的数据的唯一一种方式
mutations:{
SET_TOKEN(state,payload){
// state是vuex默认提供的 payload载荷 提交突变传参 payload接收突变传递参数
state.token = payload
},
},
// 动作 异步操作
actions:{
// 登录获取token 提交突变 把token传给突变 突变-->设置给state中token
login(sto,payload){
// sto类仓库对象 默认提供 commit提交突变 dispacth
// 假设发送完成异步请求
let token = 'esfkhsdakfjlskjfdlsjglkasdkfskfdasdasfksadf';//token就是后端获取数据token
// 将token提交给突变
sto.commit('SET_TOKEN',token);
console.log(sto,payload,'22222');
}
}
};
// 2.创建状态机实例
let store = new Vuex.Store(storeConfig);
//3.注册状态机实例
new Vue({
el:"#app",
store,
data:{ },
methods:{
//辅助函数的写法
...mapMutations(['SET_TOKEN']),
...mapActions(['login']),
// 相当于 login(){}
},
computed:{
// 引入辅助函数所对应的状态/数据 mapState('命名空间',['','',''])
...mapState(['public','token']),
...mapGetters(['Upper'])
},
})
</script>
</body>