Vue学习笔记
1.1、nodeJs
在安装vue之前,我们首先要在电脑上安装nodeJs,在百度上搜索nodeJs就可以下载了,其次还需要安装Visual Studio Code,这个是前端开发的工具,安装成功后即可安装vue了。
1.2、Vue的安装
vue的官网:vuejs.org
另外推荐使用v3.cn.vuejs.org
ctrl+R调出运行窗,输入cmd打开控制器终端,输入vue下载安装指令。
cnpm install -g @vue/cli
等待安装完成,在控制终端输入
vue --version
检测vue是否安装成功。
1.2.1、创建项目
打开VSCode,在盘符中创建一个文件夹用于存放项目代码,选择打开文件夹,选中创建的文件夹,打开项目后右键该项目,选择“在集成终端中打开”,在终端中输入如下指令创建vue项目:
vue create vue-demo
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LjFTN8fJ-1662712197001)(D:\xmImg\image-20220908143558400.png)]
1.2.2、创建时可能遇到的问题
在创建项目时,可能会遇到创建失败并报错的情况,大致内容为“禁止运行脚本”问题,这种情况为没有权限,使用
get -ExecutionPolicy
指令查看该权限,若结果为无权限,则使用如下代码修改权限:
set -ExecutionPolicy RemoteSigned
VSC指令选择为上下键,勾选和取消为空格键,回车键确认。
在创建项目时,建议将Manually select features勾选,将Linter/Formatter取消勾选。
1.2.3、运行项目
cd vue-demo
npm run serve
1.2.4、安装vue高亮插件
在运行vue项目后,查看代码时全黑状态,可点击VSC编辑器左边栏如下的操作按钮,在输入框中输入volar,选择骷髅头样式的,下载安装即可。关闭终端为ctrl+J。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bBZhiQqJ-1662712197003)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20220908144342711.png)]
1.3、vue模板语言
vue的模板语言为双花括号:{{}},项目访问路径默认为localhost:8080
assets文件用于存放静态文件,app.vue是根组件,components是组件
1.3.1、vue中变量的创建与使用
vue中通过data函数创建变量,并通过{{变量}}的方式取值,如:
<template>
<h3>message={{message}}</h3>
</template>
<script>
export default {
name: 'HelloWorld',
data(){
return{
message:"测试"
}
}
}
</script>
1.3.2、v-html指令
v-html指令能直接传输html标签,如下:
<template>
<div v-html="rawhtml"></div>
</template>
<script>
export default {
name: 'HelloWorld',
data(){
return{
rawhtml:"<a href='https://www.baidu.com'>百度</a>"
}
}
}
</script>
1.3.3、v-bind指令
v-bind用于绑定一个或多个属性值,或者向另一个组件传递props值
<div id="app">
<!-- 不能使用mustache语法 把imgURL直接当成字符串 在内容里面才能使用-->
<!-- <img src="{{imgURL}}" alt=""> -->
<img v-bind:src="imgURL" alt="">
<a v-bind:href="aHref">百度一下</a>
<a :href="aHref">百度一下</a>
</div>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
message: 'nihao',
imgURL:'https://m.360buyimg.com/babel/jfs/t1/49107/14/3176/6019/5d0eea59E238562fd/2576bcda7fc37edd.jpg',
aHref:'http://www.baiu.com'
}
})
</script>
很多时候,我们希望动态的来切换class,比如:
当数据为某个状态时,字体显示红色。
当数据另一个状态时,字体显示黑色。
绑定class有两种方式:
对象语法
数组语法
对象语法动态绑定class
对象语法的含义是:class后面跟的是一个对象。
.active{
color:red;
}
<div id="app">
<h2 :class="active">{{message}}</h2>
</div>
<script>
const app = new Vue({
el: '#app',
data: {
message: 'nihao',
active:'active'
},
}
<h2 v-bind:class="{key:value}">{{message}}</h2>
<h2 v-bind:class="{类名:boolean}">{{message}}</h2>
<h2 v-bind:class="{active:true,line:false}">{{message}}</h2>
boolean值为true的时候,类就被添加。
一般把boolean值放到data中
<h2 v-bind:class="{active:isActive,line:isLine}">{{message}}</h2>
data: {
message: 'nihao',
isActive:true,
isLine:true
},
如果过于复杂,可以放在一个methods或者computed中
<h2 v-bind:class="getClasses()">{{message}}</h2>
<button v-on:click="btnClick">按钮</button>
methods:{
getClasses: function () {
return { active: this.isActive, line: this.isLine };
},
btnClick:function(){
this.isActive=!this.isActive;
},
}
数组语法的含义是:class后面跟的是一个数组。
<h2 class="title" :class="['active','line']">{{message}}</h2>
<!-- 没有单引号,是变量 -->
<h2 class="title" :class="[active,line]">{{message}}</h2>
v-bind绑定style
我们可以利用v-bind:style来绑定一些CSS内联样式。
我们可以使用驼峰式 (camelCase) fontSize
或短横线分隔 (kebab-case,记得用单引号括起来) ‘font-size’
<h2 :style="{key:value}">{{message}}</h2>
<h2 :style="{属性名:属性值}">{{message}}</h2>
<!-- 如果不加单引号,则是变量 -->
<h2 :style="{fontSize:'50px'}">{{message}}</h2>
<h2 :style="{fontSize:finalSize,color:finalColor}">{{message}}</h2>
<h2 :style="getStyles()">{{message}}</h2>
data: {
message: 'nihao',
finalSize:'100px',
finalColor:'red'
},
methods:{
getStyles:function(){
return { fontSize: this.finalSize, color: this.finalColor }
}
}
v-bind :id可改写为:id=“XXXX”
1.3.4、js表达式
vue支持使用表达式的方式,如
{{num+1}}
{{flag?"正确":"错误"}}
{{message.split("").revuerse().join("")}}
注意,表达式中只能绑定单个表达式!
1.4、渲染
1.4.1、条件渲染
所谓条件渲染,就是vue可用于做条件处理的方法,如v-if,v-show等,v-if在渲染页面时,若不为true,整个组件会被删除,而v-show则不是,它时基于css的消失,即style=“display:none”。
<template>
<p v-if="flag">正确时才显示</p>
<p v-else>否则的情况下显示</p>
<p v-show="flag">flag为true时显示哦</p>
</template>
<script>
export default {
name: 'HelloWorld',
data(){
return{
flag:true
}
}
}
</script>
1.4.2、列表渲染
<template>
<ul>
<li v-for="item in items">name={{item.name}}</li>
</ul>
</template>
<script>
export default {
name: 'HelloWorld',
data(){
return{
items:[{
id:1,
name:"张三"
},{
id:2,
name:"李四"
}
]
}
}
}
</script>
维护状态:数组中加入一条数据,列表渲染这一条时,不会重新把所有的都渲染一遍,实现方法:
<template>
<ul>
<li v-for="item in items" :key="item.id">name={{item.name}}</li><!--加入:key-->
</ul>
</template>
<script>
export default {
name: 'HelloWorld',
data(){
return{
items:[{
id:1,
name:"张三"
},{
id:2,
name:"李四"
}
]
}
}
}
</script>
1.4.3、事件处理
v-on添加一个事件,可简写为@
事件的处理方法为methods,与data同级,用“,”隔开,在事件中,读取data中的属性,需要用this属性,方法中的event参数是原生Domevent。
<template>
<p>{{message}}</p>
<button v-on:click="oneClick">点击1</button>
</template>
<script>
export default {
name: 'HelloWorld',
data(){
return{
message:""
}
},
methods:{
oneClick(event){
this.message="点击1",
event.target.innerHTML="点击之后"
}
}
}
</script>
内联处理器中的方法
通俗点说就是传参
<template>
<p>{{message}}</p>
<button @click="say('hi')">hi</button>
<button @click="say('hello')">hello</button>
</template>
<script>
export default {
name: 'HelloWorld',
data(){
return{
message:""
}
},
methods:{
say(data){
this.message=data
}
}
}
</script>
1.4.4、表单输入绑定
在日常开发过程中,获取表单填入的数据是非常重要的。
<template>
用户名: <input type="text" v-model="username"/>
<p>{{username}}</p>
密码: <input type="text" v-model="password"/>
<p>{{password}}</p>
</template>
<script>
export default {
name: 'HelloWorld',
data(){
return{
username:"",
password:""
}
}
}
</script>
修饰符lazy
v-model在input输入同时,可以加入一个lazy属性,只有在改变结束时同步获取数据,能减少不适感和内存占用。
trim可去除多余的空格
<template>
用户名: <input type="text" v-model.lazy="username"/>
<p>{{username}}</p>
密码: <input type="text" v-model.trim="password"/>
<p>{{password}}</p>
</template>
<script>
export default {
name: 'HelloWorld',
data(){
return{
username:"",
password:""
}
}
}
</script>
2.1、组件
2.1.1、单文件组件
*.vue是特殊的文件格式,内容分为三个部分,html标签位置、
在App.vue的script中,引入某个自定义的vue组件(自己写的页面)
import HelloWorld from './components/HelloWorld.vue'
挂载该组件
export default {
name: 'App',
components: {
HelloWorld
}
}
显示组件
<HelloWorld/>
若是在style组件中加入scoped属性,则是表示该样式只在当前组件中使用。
2.1.2、多文件组件
props组件交互
可以在组件上注册一些自定义的attribute
在属性前加“:”可以将属性编程动态的。
定义多组件交互,共分为以下几个步骤:
1、定义一个自己的组件,即*.vue文件,在script标签中标注自己的名字,如:
export default {
name: 'MyApp'
}
2、在App.vue中挂载自己的组件,挂载方式见上面。
3、在app.vue中定义一个变量,变量赋值到标签上,如
4、在自己定义的组件中接收该值并显示
实现代码如下:
MyComponent.vue
<template>
<h3>{{title}}</h3>
</template>
<script>
export default{
name:"myComponent",
props:{
title:{
type:String,
default:""
}
}
}
</script>
<style scoped>
</style>
app.vue
<template>
<img alt="Vue logo" src="./assets/logo.png">
<MyComponent :title="title"/>
</template>
<script>
import MyComponent from './components/MyComponent.vue'
export default {
name: 'App',
data(){
return{
title:"我是标题"
}
},
components: {
MyComponent
}
}
</script>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>
若是type为Array,数组和对象都必须要通过使用函数进行返回,如:
defaut:function(){
return []
}
2.1.3、自定义事件的组件交互
上一个是从父传到子,这一个则是从子到父
MyComponent.vue
<template>
<button @click="sendClickHandle">点击传递</button>
</template>
<script>
export default{
name:"myComponent",
data(){
return{
Message:"我是子数据"
}
},
methods:{
sendClickHandle(){
//参数1:字符串,理论上自定义,但是需要有意义
//参数2:传递的数据
this.$emit("onEvent",this.Message)
}
}
}
</script>
<style scoped>
</style>
app.vue
<template>
<img alt="Vue logo" src="./assets/logo.png">
<MyComponent @onEvent="getDataHandle"/>
<p>{{message}}</p>
</template>
<script>
import MyComponent from './components/MyComponent.vue'
export default {
name: 'App',
data(){
return{
message:""
}
},
components: {
MyComponent
},
methods:{
getDataHandle(data){
this.message=data;
}
}
}
</script>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>
2.2.1、组件生命周期
创建时:beforeCreate、create
渲染时:beforeMount、mounted
更新时:beforeUpdate、update
卸载时:beforeUnmount、unmounted
3.1、第三方 swiper
swiper是第三方的滑动触摸插件,先需要下载安装
官网:swiperjs.com.cn
swiper.com.cn
cnpm install --save swiper@8.1.6
使用swiper制作轮播图
<template>
<swiper>
<swiper-slide>
<img src="../assets/linai.jpg" alt=""/>
</swiper-slide>
<swiper-slide>
<img src="../assets/linai.jpg" alt=""/>
</swiper-slide>
<swiper-slide>
<img src="../assets/linai.jpg" alt=""/>
</swiper-slide>
</swiper>
</template>
<script>
import {Swiper,SwiperSlide} from 'swiper/vue'
import 'swiper/css'
export default {
name: 'HelloWorld',
components:{
Swiper,
SwiperSlide
}
}
</script>
<style scoped>
img{
width:auto;
}
</style>
加入指示器
<template>
<swiper :modules="modules" :pagination="{clickable:true}">
<swiper-slide>
<img src="../assets/linai.jpg" alt=""/>
</swiper-slide>
<swiper-slide>
<img src="../assets/linai.jpg" alt=""/>
</swiper-slide>
<swiper-slide>
<img src="../assets/linai.jpg" alt=""/>
</swiper-slide>
</swiper>
</template>
<script>
import { Pagination } from 'swiper'
import {Swiper,SwiperSlide} from 'swiper/vue'
import 'swiper/css'
import 'swiper/css/pagination'
export default {
name: 'HelloWorld',
components:{
Swiper,
SwiperSlide
},
data(){
return{
modules:[Pagination]
}
}
}
</script>
<style scoped>
img{
width:auto;
}
</style>
4.1、网络请求
4.1.1、Axior
Axior是基于promise的网络请求库
安装:
cnpm install --save axios
格式转换:
请求数据需要做格式转换,安装一个queryString
cnpm install --save querystrig
使用(局部引入):
get请求:
<template>
</template>
<script>
import axios from 'axios'
import querystring from 'querystring';
export default {
name: 'HelloWorld',
mounted(){
axios({
method:"get",
url:"XXXX"
}).then(res=>{
//成功后对数据处理的代码
})
}
}
</script>
post请求
<template>
</template>
<script>
import axios from 'axios'
import querystring from 'querystring';
export default {
name: 'HelloWorld',
mounted(){
axios({
method:"post",
url:"XXXX",
data:querystring.stringify({
id:1
})
}).then(res=>{
//成功后对数据处理的代码
})
}
}
</script>
<style scoped>
</style>
简写版
get请求:
axios.get(url).then(res=>{})
post请求
axios.post(url,querystring.stringify().then(res=>{}))
4.1.2、全局引入
上面的方法是局部引入axios,每到一个页面就需要引入一次,增加了代码量,于是便有了全局引入的解决方案。
在main.js中引入:
import { createApp } from 'vue'
import App from './App.vue'
//引入axios
import axios from 'axios'
//挂载到全局
const app = createApp(App)
app.config.globalProperties.$axios=axios
app.mount('#app')
//createApp(App).mount('#app')改写成上方形式
使用:上面定义成了 符号,这边使用就用 符号,这边使用就用 符号,这边使用就用符号
HelloComponent.vue
this.$axios.post(url,querystring.stringify().then(res=>{}))
this.$axios.get(url).then(res=>{})
4.1.3、Axios网络请求封装
在日常的开发中,一个项目的网络请求往往很多,此时一般采取将网络请求封装起来的方法。
在src目录下新建一个utils文件夹,创建一个request.js文件
import axios from 'axios'
import { config } from 'process'
import querystring from 'querystring'
const instance=axios.create({
timeout:5000
})
const errorHandle=(status,info)=>{
switch(status){
case 400:
console.log("400:语意有误!");
break;
case 401:
console.log("401:服务器认证失败!");
break;
case 403:
console.log("403:服务器拒绝访问!");
break;
case 404:
console.log("404:路径错误!");
break;
case 500:
console.log("500:服务器错误!");
break;
case 502:
console.log("502:服务器无响应!");
break;
default:
console.log(info);
break;
}
}
//发送数据之前
instance.interceptors.request.use(
config=>{
if(config.method==="post"){
config.data=querystring.stringify(config.data)
}
return config;
},
error=>{
return Promise.reject(error)
}
)
//获取数据之前
instance.interceptors.response.use(
response=>{
return response.status===200?Promise.resolve(response):Promise.reject(response)
},
error=>{
const{response}=error;
//错误处理最关键
errorHandle(response.status,response.info)
}
)
export default instance;
网络请求集中放在src目录下的api文件夹中的名为path.js的文件中
const base ={
//公工路径,如www.baidu.com,至于后面的/XXX不写
baseUrl:"http://www.XXX.com",
shengyubufen:"/XXXX"
}
再建一个名为index.js的文件
import axios from "../utils/request";
import path from "./path"
const api={
getXXX(){
return axios.get(path.baseUrl+path.shengyubufen)
}
}
export default api;
测试HelloWorld.vue
<template>
</template>
<script>
import api from "../api/index"
import querystring from 'querystring';
export default {
name: 'HelloWorld',
mounted(){
api.getXXX().then(res=>{
console.log(res.data)
})
}
}
</script>
<style scoped>
</style>
4.1.4、网络请求跨域问题
js采取的是同源策略
同源策略是浏览器的一项安全策略,浏览器只允许js代码请求喝当前所在服务器域名、端口、协议相同的数据接口上的数据,这就是同源策略。
也就是说,当协议、域名、端口任意一个不相同时,就会产生跨域问题
Access to XMLHttpRequest at ‘XXXXXXXX’
目前主流的跨域解决方案有两种:
①、后台解决:cors
②、前台解决:proxy
在vue.config.js文件中写如下代码:
const { defineConfig } = require('@vue/cli-service')
module.exports = defineConfig({
transpileDependencies: true,
devServer:{
proxy:{
'/api':{
//只需要把域名放入就行了
target:'<url>',
changeOrigin:true
}
}
}
})
温馨提示:解决完跨域问题后,记得重启服务器!
5.1、vue-router管理路由
在vue中,我们可以通过vue-router路由管理页面之间的关系
vue-router是vue.js的官方路由,它与vue.js核心深度集成,让用vue.js构建单页应用变得轻而易举
5.1.1、安装
npm install -save vue-router
5.1.2、配置独立的路由文件
index.js
import { createRouter,createWebHashHistory} from "vue-router"
import HomeView from'../view/HomeView.vue'
//配置信息中需要页面的相关配置
const routes = [
{
path:"/",
name:"home",
//名为HomeView的vue页面
component:HomeView
},{
path:"/about",
name:"about",
//异步加载 名为AboutView.vue的vue页面
component:()=>import("../view/AboutView.vue")
}
]
const router = createRouter({
history:createWebHashHistory(),
routes
})
export default router;
测试时需建立两个以上vue页面,此处分别为名为HomeView.vue的文件和AboutView.vue的文件
主入口引入router(main.js)中
import { createApp } from 'vue'
import App from './App.vue'
import router from "./router"
createApp(App).use(router).mount('#app')
在Hello World中配置路由的显示入口
<template>
<router-view></router-view>
</template>
<script>
export default {
name: 'HelloWorld'
}
</script>
此时访问页面,该页面会加载在HelloWorld中,且路径变成了http://localhost:8081/#/,在后面加上about即可访问关于页面。
<template>
<router-view></router-view>
<router-link to="/">首页</router-link>
<router-link to="/about">关于</router-link>
</template>
<script>
export default {
name: 'HelloWorld'
}
</script>
上方为加上跳转按钮的实现代码。
5.1.3、createWebHashHistiry与createWebHistiry的区别
createWebHashHistiry:路径上会有”/#“
createWebHistiry:此种方式需要后台配合做重定向,否则会404
原理:
createWebHashHistiry:a标签锚点连接
createWebHistiry:H5 push state()
5.1.4、路由传参
页面跳转过程中,往往会有传参的情况,因此便有了如下解决方案
搭建项目时,可勾选router,这样就不用自己再创建了
创建完成后,可建立一个vue页面,这里以news为例
先创建vue文件,再去index.js中配置该文件的路径
NewsView.vue
<template>
<h3>新闻</h3>
<ul>
<li><router-link to="details/百度">百度</router-link></li>
<li><router-link to="details/网易">网易</router-link></li>
<li><router-link to="details/头条">头条</router-link></li>
</ul>
</template>
NewsDetails.vue
<template>
<h3>新闻详情</h3>
<p>{{ $route.params.name }}</p>
</template>
HelloWorld.vue
<template>
<router-view></router-view>
<router-link to="/">首页</router-link>
<router-link to="/about">关于</router-link>
<router-link to="/news">新闻</router-link>
</template>
<script>
export default {
name: 'HelloWorld'
}
</script>
index.js
{
path:"/news",
name:"news",
component:()=>import("../view/NewsView.vue")
},
{
path:"/details/:name",
name:"details",
component:()=>import("../view/NewsDetails.vue")
}
其中 path:“/details/:name”,中”/:name“为参数
路由传递参数共分为三步:
第一步:咋路由配置中指定参数的key,即上面写到的”/:name”
第二步:在跳转过程中携带参数,即to=“details/百度”
第三步:在详情页面读取路由携带的参数,即{{ $route.params.name }}
5.1.5、嵌套路由配置
例如:左边导航时的父子导航
现在view文件夹下创建一个名为AboutSub的文件夹,在此文件夹下创建两个vue文件,分别为AboutInfo.vue、AboutUs.vue
AboutInfo.vue
<template>
<h3>信息</h3>
</template>
<script>
</script>
<style scoped></style>
AboutUs.vue
<template>
<h3>我们</h3>
</template>
<script>
</script>
<style scoped></style>
然后在index.js中配置该页面的路径
{
path:"/about",
name:"about",
//异步加载 名为AboutView.vue的vue页面
component:()=>import("../view/AboutView.vue"),
children:[{
//二级导航的路径不要加
path:"us",
component:()=>import("../view/AboutSub/AboutUs.vue")
},
{
//二级导航的路径不要加
path:"info",
component:()=>import("../view/AboutSub/AboutInfo.vue")
}]
}
再去到aboutView.vue中配置路径
<template>
//此处要写全路径
<router-link to="/about/us">关于我们</router-link>
<router-link to="/about/info">关于信息</router-link>
<router-view></router-view>
</template>
<script></script>
<style scoped></style>
重定向:redirect:“/about/us”
5.2、vuex状态管理
Vuex是一个专为Vue.js 应用程序开发的状态管理模式+库。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。
简单来说,状态管理可以理解成为了更方便的管理组件之间的数据交互,提供了一-个集中式的管理方案,任何组件都可以按照指定的方式进行读取和改变数据。
5.2.1、安装
npm install --save vuex
5.2.2、配置
在src目录下创建一个store文件夹,文件夹中创建一个名为index.js的文件
import { createStore } from "vuex"
//vuex的核心作用就是帮我们管理组件之间的状态的
export default createStore({
//所有的状态都放在这里(数据)
state:{
counter:0
}
})
将这个文件引入到main.js中
import store from './store'
createApp(App).use(store).mount('#app')
在组件中读取状态(测试)
//HelloWorld中
<p>{{ $store.state.counter }}</p>
//App.vue中
<p>{{ $store.state.counter }}</p>
如果在一个组件中读取很多次,则用下面的方法
<template>
<p>{{ counter }}</p>
</template>
<script>
import {mapState} from "vuex"
export default {
name: 'HelloWorld',
computed:{
...mapState(["counter"])
}
}
</script>
<style scoped>
</style>
5.3、vuex状态管理核心
最常用的核心概念包含:State、Getter、Mutation、Action
5.3.1、Getter
对vuex中的数据进行过滤(store文件夹下index.js)
import { createStore } from "vuex"
//vuex的核心作用就是帮我们管理组件之间的状态的
export default createStore({
//所有的状态都放在这里(数据)
state:{
counter:0
},
getters:{
getCounter(state){
return state.counter>0?state.counter:"异常"
}
}
})
测试(HelloWorld)
<template>
<p>{{ $store.getters.getCounter }}</p>
</template>
<script>
export default {
name: 'HelloWorld'
}
</script>
<style scoped>
</style>
另一种方案
<template>
<p>{{ $store.getters.getCounter }}</p>
<p>{{ getCounter }}</p>
</template>
<script>
import { mapGetters } from 'vuex';
export default {
name: 'HelloWorld',
components:{
},
computed:{
...mapGetters(["getCounter"])
}
}
</script>
<style scoped>
</style>
5.3.2、Mutation
更改Vuex的store中的状态的唯一方法是提交mutationVuex中的mutation非常类似于事件:每个mutation都有一个字符串的事件类型(type)和一个回调函数(handler)。这个回调函数就是我们实际进行状态更改的地方,并且它会接受state作为第一个参数。
index.js
import { createStore } from "vuex"
//vuex的核心作用就是帮我们管理组件之间的状态的
export default createStore({
//所有的状态都放在这里(数据)
state:{
counter:10
},
getters:{
getCounter(state){
return state.counter>0?state.counter:"异常"
}
},
mutations:{
addCounter(state,num){
state.counter+=num
}
}
})
helloworld.vue
<template>
<button @clock="addClick">增加</button>
</template>
<script>
import { mapGetters } from 'vuex';
export default {
name: 'HelloWorld',
components:{
},
computed:{
...mapGetters(["getCounter"])
},
methods:{
addClick(){
this.$store.commit("addCounter",16)
}
}
}
</script>
<style scoped>
</style>
第二种方式
<template>
<button @clock="addClick">增加</button>
</template>
<script>
import { mapGetters, mapMutations } from 'vuex';
export default {
name: 'HelloWorld',
components:{
},
computed:{
...mapGetters(["getCounter"])
},
methods:{
...mapMutations(["addCounter"]),
addClick(){
//this.$store.commit("addCounter",16)
this.addCounter(20)
}
}
}
</script>
<style scoped>
</style>
5.3.3、Action
Action类似于mutation,不同在于:
●Action 提交的是mutation,而不是直接变更状态
●Action 可以包含任意异步操作
idex.js
import axios from "axios"
//为异步操作准备的
actions:{
ansyncAddCounter({commit}){
axios.get("XXXXXXX").then(res=>{
commit("addCounter",res.data[0])
})
}
}
helloworld.vue
<template>
<div class= "home">
< img
alt="Vue logo"
src=". ./as sets/ logo . png">
<h3> home< /h3>
<p> count={{ $store . getters. getCounter }}</p>
<p>{{ getCounter }}</p>
<button @click=" addClickHandle" >增加< /button>
<button @click=" addAsyncClickHandle">异步增加< /button>
</div>
</ template>
<script>
import { mapGetters , mapMutations,mapActions } from "vuex"
export default {
name: ' HomeView'
components: {
},
computed:{
. mapGetters([" getCounter" ])
},
methods:{
.. . mapMutations ([" addCounter"]),
... mapActions( ["asyncAddCounter"]),
addClickHandle(){
//固定调用方式
/ this . $store. commit(”addCounter" ,15)
this . addCounter(20)
};
addAsyncCl ickHandle( ){
// this . $store . dispatch("asyncAddCounter");| I
this . asyncAddCounter();
}
</script>
Click">增加
#### 5.3.3、Action
Action类似于mutation,不同在于:
●Action 提交的是mutation,而不是直接变更状态
●Action 可以包含任意异步操作
idex.js
```vue
import axios from "axios"
//为异步操作准备的
actions:{
ansyncAddCounter({commit}){
axios.get("XXXXXXX").then(res=>{
commit("addCounter",res.data[0])
})
}
}
helloworld.vue
<template>
<div class= "home">
< img
alt="Vue logo"
src=". ./as sets/ logo . png">
<h3> home< /h3>
<p> count={{ $store . getters. getCounter }}</p>
<p>{{ getCounter }}</p>
<button @click=" addClickHandle" >增加< /button>
<button @click=" addAsyncClickHandle">异步增加< /button>
</div>
</ template>
<script>
import { mapGetters , mapMutations,mapActions } from "vuex"
export default {
name: ' HomeView'
components: {
},
computed:{
. mapGetters([" getCounter" ])
},
methods:{
.. . mapMutations ([" addCounter"]),
... mapActions( ["asyncAddCounter"]),
addClickHandle(){
//固定调用方式
/ this . $store. commit(”addCounter" ,15)
this . addCounter(20)
};
addAsyncCl ickHandle( ){
// this . $store . dispatch("asyncAddCounter");| I
this . asyncAddCounter();
}
</script>