vue基础
是什么—javascript框架
构建用户界面的前端框架
1.构建用户界面
用vue往html页面中填充数据
2.框架
现成的解决方案,遵守框架的规范去实现自己的业务功能
学习vue 就是学习vue框架中规定的用法
vue的指令组件(对ul结构的复用),路由,vuex,vue组件库
vue框架的主要特性
数据驱动视图
数据的变化驱动页面的更新变化(单向)
程序员只需维护好数据,页面结构被vue自动渲染出来
双向数据绑定
在网页中,form表单负责采集数据,Ajax负责提交数据
两个特性的底层原理—MVVM
vue基础操作
el挂载点
data数据对象
methods方法
提供methods中的所有函数,其中的this都指向当前实例
与computed计算属性的区别
computed计算属性
一旦计算出结果,立刻缓存,下一次读取,直接读取缓存,性能较高
简写
<body>
<!-- 2.控制的dom元素区域 -->
<div id="app">
<h3>小黑的礼物清单</h3>
<table border="1" cellspacing="0">
<tr>
<th>名字</th>
<th>数量</th>
</tr>
<tr v-for="(item,index) in lists" :key="item.id">
<td>{{item.name}} </td>
<td>{{item.num}} </td>
</tr>
</table>
<!-- 计算属性本质是属性,不能写成函数totalCount() -->
<p>礼物总数:{{totalCount}} 个</p>
</div>
<!-- 1.引入vue.js -->
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<!-- 3.vue实例对象 -->
<script>
let app=new Vue({
el:'#app',
data:{
lists:[
{id:1,name:"篮球",num:1},
{id:2,name:"足球",num:3},
{id:3,name:"排球",num:5},
]
},
computed:{
// 对数组求和-->reduce(函数,初始值)
//this.lists.reduce((sum,item)=>item.num+sum,0)
totalCount(){
return this.lists.reduce((sum,item)=>item.num+sum,0)
}
}
})
</script>
</body>
完整写法
<body>
<!-- 2.控制的dom元素区域 -->
<div id="app">
姓: <input type="text" v-model="firstname">
+
名: <input type="text" v-model="lastname">
=
{{fullname}}
<br>
<button @click="changeName">改名卡</button>
</div>
<!-- 1.引入vue.js -->
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<!-- 3.vue实例对象 -->
<script>
let app=new Vue({
el:'#app',
data:{
firstname:"刘",
lastname:"备"
},
methods:{
changeName(){
this.fullname='赵云'
}
},
computed:{
// //简写->获取
// fullname(){
// return this.firstname+this.lastname
// }
//完整写法-》获取+设置
fullname:{
// 1.当fullname计算属性,被获取求值时,执行get(由缓存读取缓存),将返回值作为最终的结果
get(){
return this.firstname+this.lastname
},
//2.当fullname计算属性,被修改赋值的时候,执行set,修改的值传给set方法的形参
set(value){
this.firstname=value.slice(0,1)
this.lastname=value.slice(1)
}
}
}
})
</script>
</body>
watch侦听器(监视器)
<body>
<!-- 2.控制的dom元素区域 -->
<div id="app">
<textarea v-model="obj.words"></textarea>
</div>
<!-- 1.引入vue.js -->
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<!-- 3.vue实例对象 -->
<script>
let app=new Vue({
el:'#app',
data:{
// words:'',
obj:{
words:''
}
},
//在事件发生变化的时候触发执行
watch:{
//old一般不用
// words(newval,oldval){
// console.log(oldval+"变为了"+newval);
// }
'obj.words'(newval,oldval){
console.log(oldval+"变为了"+newval);
}
}
})
</script>
</body>
指令
Vue 根据不同的指令,针对标签实现不同的功能
指令:
带有V-前缀的特殊的标签属性
本质:属性
基本使用步骤
内容填充
插值表达式
v-text
v-html
能够解析标签
注册事件
v-on基础
<body>
<div id="app">
<button v-on:click="count++">+</button>
{{count}}
<button v-on:click="count--">-</button>
</div>
<!-- 1.引入vue.js -->
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<!-- 3.vue 的实例对象-->
<script>
let app=new Vue(
{
//指定控制的dom区域
el:'#app',
//数据源
data:{
count:20,
}
}
)
</script>
</body>
<body>
<!-- 操作的dom区域 -->
<div id="app">
<input type="button" value="vue-on指令" v-on:click="doIt">
<input type="button" value="vue-on简写" @click="doIt">
<p @click="changeFood"> {{food}} </p>
</div>
<!-- 引入vue.js -->
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<!-- 创建vue实例对象 -->
<script>
let app=new Vue({
el:'#app',
data:{
food:'potato'
},
methods:{
doIt:function(){
alert('do it')
},
changeFood:function(){
this.food+=' is tasty!'
}
}
})
</script>
</body>
v-on补充(传递参数,事件修饰符)
<body>
<div id="app">
<input type="button" value="可乐5元" @click="buy(5)">
<input type="button" value="咖啡10元" @click="buy(10)">
<h2> 余额{{money}}</h2>
</div>
<!-- 1.引入vue.js -->
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<!-- 3.vue 的实例对象-->
<script>
let app=new Vue(
{
//指定控制的dom区域
el:'#app',
//数据源
data:{
money:990
},
methods:{
buy(price)
{
this.money-=price
}
}
}
)
</script>
</body>
元素的显示与隐藏
v-show
v-show :通过表达式的真假切换元素的显示状态
本质: 改变元素的display属性,仍然存在
适用频繁切换的场景
<body>
<!-- 控制的元素dom区域 -->
<div id="app">
<!-- <button @click="changeIsshow">切换显示状态</button> -->
<button @click="add">年龄触发</button>
<img src="../照片/014b4e62ccddaf0002c45e373609e6.webp.jpg" v-show="age>=18">
</div>
<!-- 引入vue.js -->
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<script>
// 创建vue实例对象
let app=new Vue({
el:'#app',
data:{
isshow: false,
age:17
},
methods:{
changeIsshow: function(){
this.isshow = ! this.isshow
},
add:function()
{
this.age++
}
}
})
</script>
</body>
v-if
v-if :通过表达式的真假切换元素的显示状态
本质:直接操作dom元素,添加或者删除元素
v-else
v-esle-if
要搭配V-if使用
<body>
<!-- 2.控制的dom元素区域 -->
<div id="app">
<p v-if="score>=90">A</p>
<p v-else-if="score>=80">B</p>
<p v-else-if="score>=70">C</p>
<p v-else>D</p>
</div>
<!-- 1.导入vue.JS -->
<script src="https://cdn.jsdelivr.net/npm/vue@2.7.14/dist/vue.js"></script>
<!-- 3.vue实例对象 -->
<script>
let app=new Vue({
el:'#app',
data:{
score:80
}
})
</script>
</body>
<body>
<
<!-- 2.控制的dom区域 -->
<div id="app">
<input type="button" value="切换显示" @click="toggleIsShow">
<p v-if="isShow">我是p标签</p>
</div>
<!-- 1.引入vue -->
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<!-- 3.创建vue实例对象 -->
<script>
let app=new Vue(
{
el:'#app',
data:{
isShow:true
},
methods:{
toggleIsShow:function(){
this.isShow=!this.isShow
}
}
}
)
</script>
</body>
设置元素的属性
v-bind
v-bind : 设置html标签的属性,如src,url…
3.1完整写法:v-bind:属性名
3.2简略写法::属性名
<body>
<!-- 3.v-bind : 设置元素的属性
3.1完整写法:v-bind:属性名
3.2简略写法::属性名
-->
<!-- 2.vue操作的dom区域 -->
<div id="app">
<!-- <img v-bind:src="imgSrc">
<img v-bind:title="imgTitle">
<img v-bind:class="isActive?'active':' ' ">
<img v-bind:src="{active:isActive}"> -->
<!-- 简化写法 -->
<!-- <img :src="imgSrc" alt="">
<br>
<img :src="imgSrc" :title="imgTitle+'!!!' " alt="">
<br> -->
<img :src="imgSrc" :class="isActive ? 'active' : ' ' " alt="" @click="changeColor">
<!-- <br>
<img :src="imgSrc" :class="{active:isActive}" alt=""> -->
</div>
<!--1. 导入vue.js -->
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<!-- 3.创建Vue实例对象 -->
<script>
let app=new Vue({
el:"#app",//操作的dom区域
data:{
imgSrc:"../照片/014b4e62ccddaf0002c45e373609e6.webp.jpg",
imgTitle:"my",
isActive: false
},
methods:{
changeColor:function(){
this.isActive=!this.isActive
}
}
})
</script>
</body>
v-bind对样式控制的增强
操作class
操作style
<div id="app">
<div class="big" :style="{backgroundColor:'red','background-color':'black' }">
<p>MY TEST</p>
</div>
</div>
根据数据渲染,多次渲染整个元素
v-for
v-for="(item,index) in arr
<body>
<!-- 控制的dom元素区域 -->
<div id="app">
<ul>
<li v-for="(item,index) in arr">
{{index}} {{item}} 你好
</li>
<li v-for="(item,indecex) in obj">
{{ item.name }}
</li>
</ul>
</div>
<!--导入vue.js -->
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<!-- vue实例对象区域 -->
<script>
let app=new Vue({
el:'#app',
data:{
arr:[2,31,2,5,6,6],
obj:[
{name:"alice"},
{name:"bob"},
{name:"sjeiwhr"}
]
}
})
</script>
</body>
v-for中的key
给元素添加的唯一标识
<body>
<h1>小黑的书架</h1>
<div id="app">
<ul>
<li v-for="(item,index) in bookList" :key="item.id">
<span>{{item.name}} </span>
<span>{{item.author}} </span>
<button @click="del(item.id)">删除</button>
</li>
</ul>
</div>
<!--导入vue.js -->
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<!-- vue实例对象区域 -->
<script>
let app=new Vue({
el:'#app',
data:{
bookList:[
{id:1,name:'红楼梦',author:'曹雪芹'},
{id:2,name:'三国演义',author:'罗贯中'},
{id:3,name:'水浒传',author:'施耐庵'},
{id:4,name:'西游记',author:'吴承恩'},
]
},
methods:{
del(id){
//根据当前的id删除对应项
//filter:返回满足条件的新数组
this.bookList=this.bookList.filter(item => item.id!==id)
}
}
})
</script>
</body>
获取或设置表单元素的值
v-model
双向数据绑定,修改表单里的值会影响数据
应用于input
<body>
<!-- 控制的dom元素区域 -->
<div id="app">
<input type="text" v-model="message" @keyup.enter="getM">
<input type="button" value="修改message" @click="setM">
<h2>{{message}} </h2>
</div>
<!--导入vue.js -->
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<!-- vue实例对象区域 -->
<script>
let app=new Vue({
el:'#app',
data:{
message:"my code"
},
methods:{
setM:function(){
alert(this.message)
},
getM:function(){
alert(this.message)
}
}
})
</script>
</body>
应用于其他表单元素
指令修饰符
Vue生命周期
一个vue实例从创建到销毁的整个过程
分为四个阶段
创建,:响应式数据
挂载,:渲染模板
更新,:数据修改,更新视图
销毁,: 销毁实例
生命周期函数(钩子函数)
在vue生命周期中自动运行的一些函数
工程化开发
脚手架
组件化开发
组件化
将页面拆分成一个个组件,每个组件有自己独立的结构,样式,行为
好处:
便于维护,复用
分类:
普通组件,根组件
根组件
整个应用最上层的组件,包裹所有的普通组件
一个根组件App.vue,包含三部分:
template结构:只有一个根节点
style样式(支持less,要安装less与less-loader)
script行为
组成
<template>
<div class="app">
我是结构
<div class="box" @click="fn">aaa</div>
</div>
</template>
<script>
//导出当前组件的配置项
//可以提供data(特殊) methods computed watch 生命周期八大钩子
export default{
created(){
console.log("hello world");
},
methods:{
fn(){
alert("hello")
}
}
}
</script>
<style lang="less">
/* 让style 支持less */
/* 1.给style加上 lang='less' */
/* 2.安装依赖包 less less-loader */
.app{
width: 200px;
height: 200px;
background-color: pink;
.box{
width: 100px;
height: 100px;
background-color: blue;
}
}
</style>
普通组件的注册使用
注册方式
局部注册
只能在注册的组件内使用
1.创建组件
创建.vue文件(三个部分:结构样式行为)
2.在使用的组件内导入并注册
import 组件对象 from 'vue文件路径'
export default {
components:{
//3.注册组件
// '组件名': 组件对象
HmHeader:HmHeader,}
}
3.使用组件
<组件名></组件名>
(命名规范:大驼峰命名法)
<!-- 1.创建组件 -->
<template>
<div class="hmheader">
i am hmheader
</div>
</template>
<script>
export default {
}
</script>
<style>
.hmheader{
height: 100px;
line-height: 100px;
text-align: center;
font-size: 30px;
background-color: #8064a2;
color: white;
}
</style>
<template>
<div class="app">
<!-- 4.使用组件 -->
<!-- 头部组件 -->
<HmHeader></HmHeader>
<!-- 主体组件 -->
<HmMain></HmMain>
<!-- 底部组件 -->
<HmFooter></HmFooter>
</div>
</template>
<script>
//2.导入组件
import HmHeader from './components/HmHeader.vue'
import HmMain from './components/HmMain.vue'
import HmFooter from './components/HmFooter.vue'
export default {
components:{
//3.局部注册组件
// '组件名': 组件对象
HmHeader:HmHeader,
HmMain:HmMain,
HmFooter:HmFooter
}
}
</script>
<style>
.app{
width: 600px;
height: 700px;
background-color: pink;
}
</style>
全局注册
所有组件内都可以使用
1.创建组件
2.在main.js 里面进行导入全局注册
import Vue from 'vue'
import App from './App.vue'
//1.导入全局的组件
import HmButton from './components/HmButton'
Vue.config.productionTip = false
//2.进行全局注册
Vue.component('HmButton',HmButton)
new Vue({
el:'#app',
render:(createElement)=>{
//基于app创建元素
return createElement(App)
}
})
组件的样式冲突scoped
写在组件中的样式会全局生效-》容易造成多个组件之间的样式冲突问题
1.全局样式:默认组件中的样式会作用到全局
2.局部样式:给style 加上scoped属性,让样式只作用于当前组件
scoped原理
当前组件内的所有标签被添加data-v-hash值得属性
css选择器都是被添加[data-v-hash]的属性选择器
组件的data函数
一个组件的data选项-》必须是函数-》保证每一个组件实例拥有独立的数据对象
组件通信
组件与组件之间的数据传递
组件中的数据是独立的,无法直接访问其他组件的数据=》使用组件通信技术
父子通信
父传子props
1.给子组件标签添加自定义属性,传值
2.在子组件内通过props进行接收
3.在子组件中渲染使用
子传父emit
1.子组件内使用$emit,给父组件发送消息通知
2.父组件监听事件
3.父组件提供处理函数,形参中获取参数
非父子通信-事件总线(拓展)
兄弟之间
1.创建一个都能访问的事件总线(空vue实例)utils/EventBus.js
//1.创建一个都能访问到的事件总线(空的vue实例)
import Vue from 'vue'
const Bus=new Vue()
export default Bus
2.接收方监听Bus实例的事件
created(){
//2.在接收放进行监听Bus的事件(订阅消息)
Bus.$on('sendMsg',(msg)=>{
console.log(msg);
this.msg=msg
})
},
3.发送方触发Bus实例的事件
methods:{
clickSend(){
//3.发送方,触发事件的方式传递参数(发布消息)
Bus.$emit('sendMsg',"hello world")
}
}
//1.创建一个都能访问到的事件总线(空的vue实例)
import Vue from 'vue'
const Bus=new Vue()
export default Bus
非父子通信-provide&inject
实现跨层级地共享数据(爷孙之间)
传递数据的时候
1.简单数据类型(非响应式的)
2.复杂数据类型(响应式的)--可以往下传改变后的值
双向数据绑定
v-model
原理:
语法糖,例如在输入框上为value属性与input事件的合写
$event用于模板中,获取事件的实参
<input :value="msg" @input="msg=$event.target.value" type="text">
<input type="text" v-model="msg">
实现
<template>
<div>
<BaseSelect :cityId="cityId" @handleChange="cityId=$event "></BaseSelect>
</div>
</template>
<script>
import BaseSelect from './components/BaseSelect.vue'
export default {
components:{
BaseSelect
},
data(){
return {
cityId:'102'
}
},
}
</script>
<style>
</style>
<template>
<select :value="cityId" @change="changeFn">
<option value="101">北京</option>
<option value="102">上海</option>
<option value="103">深圳</option>
<option value="104">武汉</option>
<option value="105">广州</option>
<option value="106">重庆</option>
</select>
</template>
<script>
export default {
props:{
cityId:String
},
methods:{
changeFn(e)
{
this.$emit('handleChange',e.target.value)
}
}
}
</script>
<style>
</style>
v-model简化代码
.sync修饰符
父组件:
:属性名.sync
子组件:
this.$emit(‘update:属性名’,)
获取dom元素
运用ref和$refs可以获取dom元素或者是组件实例
查找范围—当前的组件内
添加: ref="名字"
获取: this.$refs.名字
实现组件实例的方法:
this.$refs.名字.方法名()
$ nextTick
vue 是异步更新的
想要在DOM更新完成后做某事,可以使用
n
e
x
t
T
i
c
k
t
h
i
s
.
nextTick this.
nextTickthis.nextTick()=>{
}
自定义指令
注册指令
1.全局注册指令
在main.js中
//1.全局注册指令
Vue.directive('focus',{
//inserted会在指令所在的元素,被插入到页面中触发
inserted(el){
//el 就是指令所绑定的元素
console.log(el);
}
})
<script>
export default {
//2.局部注册的指令
directives:{
//指令名:指令的配置项
focus:{
inserted(el){
el.focus()
}
}
}
}
2.使用指令
v-指令名(v-focus)
指令的值
binding-value 拿到指令的值
export default {
data(){
return {
color1:'blue',
color2:'red',
}
},
directives:{
//指令名:指令的配置项
color:{
inserted(el,binding){
//binding-value 拿到指令的值
el.style.color=binding.value
},
//update钩子,监听指令值得变化,进行dom更新操作
update(el,binding){
console.log('颜色改变了');
el.style.color=binding.value
}
}
},
指令的封装
v-loading指令
1.准备类名loading,通过伪元素提供遮罩层
2.添加或移除类名实现loading蒙层的添加或者移除
3.利用指令语法,封装v-loading 通用指令
插槽
默认插槽(一个定制的位置)
让组件内的一些结构支持自定义
组件内需要定制的结构部分 改用<slot占位</ slot>
使用组件的时候 ,在组件标签内部传入结构替换slot
后备内容(默认值)
封装组件的时候可以在‘<slot ’插槽中提供后备内容(默认显示内容)
当外部使用组件时,不传东西,则slot会显示后备内容
具名插槽(定制多处位置)
- 多个slot使用name属性区分名字
<div>
<slot name="head"></slot>
</div>
- template 配合v-slot:名字 来分发对应标签
<MyTest>
<template v-slot:head>
//简写:#head
<div>this is head</div>
</template>
</MyTest>
插槽传参语法(作用域插槽)
定义插槽的时候可以传值,给插槽上绑定数据,将来使用组件的时候可以用
1.给slot标签以添加属性的方式传值
2.所有的属性将会收集在一个对象中
3.通过template #插槽名=“变量名” 接收
单页应用程序(SPA)
所有功能在一个html页面上实现
路由
路径与组件之间的映射关系
import Vue from 'vue'
import App from './App.vue'
import My from './views/MyMusic'
import Friend from './views/MyFind'
import Message from './views/MyMessage'
//1.1.引入
import VueRouter from 'vue-router'
//1.2.安装注册Vue.use(Vue插件)
Vue.use(VueRouter)
//1.3创建路由对象
const router=new VueRouter({
//2.1创建组件配置规则
routes:[
{path:'/friend',components:Friend},
{path:'/my',component:My},
{path:'/music',component:Message},
]
})
Vue.config.productionTip = false
new Vue({
render: h => h(App),
//1.4.注入到new Vue中,建立关联
router:router
}).$mount('#app')
<template>
<div>
<div class="footer_wrap">
<a href="#/music">发现音乐</a>
<a href="#/my">我的音乐</a>
<a href="#/friend">朋友</a>
</div>
<div class="top">
<!--2.2 路由出口 -->
<router-view></router-view>
</div>
</div>
</template>
<script>
export default {
}
</script>
<style>
</style>
相关简便用法
- @ 用于绝对路径的书写,表示当前的src目录
2.router-link
导航链接 实现导航高亮效果(本质还是a标签,指定to属性,跳转)
自动添加类名
1)router-link-active
2) router-link-exact-active
导航跳转传参
1)查询参数传参
to="/path?参数名=值"(跳转)
$route.query.参数名(接收)
2)动态路由传参
路由:/path/:参数名(必须传入参数)(/path/:参数名?可以不传入参数)
跳转:to="path/值"
接收:$route.params.参数名
重定向(redirect)
问题:匹配路径之后若未匹配到组件则则会显示空白
重定向:匹配path之后强制跳转path路径
{path:'匹配路径',redirect:'重定向到的路径'}
404路由:
{path:'*',component:NotFind}
模式设置
hash 路由:(默认)
路径中含有#
history 路由:
(上线需要服务器支持)
{
routes,
mode:‘history’
}
编程式导航–基本跳转
路径跳转
1.this.$router.push('路由路径')
2.this.$router.push({
path:'路由路径'
})
路由名字跳转
this.$router.push({
name:'路由名'
})
{name:'路由名',path:'/path/xss'}
自定义创建项目
ESlint代码规范
代码规范:
一套写代码的约定规则
规则
报错解决
手动
看报错自己找
自动
基于vscode 配置插件ESlint
vuex—仓库
vue的状态管理工具
一个插件,管理vue通用的数据(购物车数据,个人信息数据)
State 保存数据
初始化环境
1.安装vuex
npm i vuex@3 --legacy-peer-deps
2.新建vuex模板文件
store/index.js
// 导入vue
import Vue from 'vue'
// 导入Vuex
import Vuex from 'vuex'
// vuex 是vue的插件,需要use一下,进行插件的安装初始化
Vue.use(Vuex)
// 创建仓库 store
const store = new Vuex.Store()
// 导出仓库
export default store
3.main.js挂载
import Vue from 'vue'
import App from './App.vue'
// 导入仓库
import store from './store'
Vue.config.productionTip = false
new Vue({
render: h => h(App),
store: store
}).$mount('#app')
使用仓库中的数据–store直接访问
4.定义数据–state
const store = new Vuex.Store({
// state 状态,即数据,类似vue组件中的data
// 区别:
// 1.data 是组件自己的数据
// 2.state 中的数据整个vue项目的组件都能访问到,
state: {
count: 100
}
}
)
5.使用数据
获取 store:
1.Vue模板中获取 this.$store
2.js文件中获取 import 导入 store
模板中: {{ $store.state.xxx }}
组件逻辑中: this.$store.state.xxx
JS模块中: store.state.xxx
使用仓库中的数据----通过辅助函数(简化)
1 组件中导入mapState
import { mapState } from 'vuex'
2.计算属性中展开运算符展开
// computed: {
// 将state中的数据定义在组件的计算属性中
// 1.一个一个return,还是会重复写
// count () {
// return this.$store.state.count
// }
// }
// 2.利用mapState()
// computed: mapState(['count'])
computed: {
...mapState(['count', 'others'])
}
}
Mutations 同步更改数据
vuex遵循单向数据流,组件中不能直接修改数据
mutations修改State数据
1.在store.js中定义mutations对象,存放修改State对象的方法
const store = new Vuex.Store({
// 开启严格模式(默认情况,vue不检测错误代码,减少成本)
strict: true,
// state 状态,即数据,类似vue组件中的data,提供整个Vue组件访问的数据
// 区别:
// 1.data 是组件自己的数据
// 2.state 中的数据整个vue项目的组件都能访问到,
state: {
count: 100,
others: '我是第二个数据'
},
// 定义mutations,提供修改数据的方法
mutations: {
// 方法里的第一个参数是当前store的state属性
// payload 载荷 运输参数 使用mutations的时候 可以传递参数 传递载荷
addCount (s,n) {
s.count +=n
}
}
}
)
2.在页面组件中提交调用
methods: {
handleAdd (n) {
this.$store.commit('addCount',n)
}
}
3.提交参数
只能提交一个参数,若有多个参数,需要包装成对象
mapMutation辅助函数
组件中导入从mutations中提取的方法
import { mapState, mapMutations } from 'vuex'
methods: {
...mapMutations(['handleAdd'])
// handleAdd (n) {
// this.$store.commit('addCount', n)
// }
}
action 异步更改数据
// action 处理异步操作
// 不能直接操作state中的数据,需要commit mutation
actions: {
handle (context, num) {
// setTimeout模拟异步操作
setTimeout(() => {
context.commit('handleAdd', num)
}, 1000)
}
}
methods: {
handleChange (num) {
// 调用action
this.$store.dispatch('handle', num)
}
}
mapAction辅助函数
getters 获取state的数据
类似于计算属性
state: {
list: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
}
getters: {
// getters函数的第一个参数是 state
// 必须要有返回值
filterList: state => state.list.filter(item => item > 5)
}
//使用
<div>{{ $store.getters.filterList }}</div>
//
mapGetters 辅助函数
computed: {
...mapGetters(['filterList'])
}
<div>{{ filterList }}</div>
module Vuex的模块化
如果把所有的状态都放在state中,当项目变得越来越大的时候,Vuex会变得越来越难以维护