听说你也想vuex入门,快来瞅瞅吧~走过路过不要错过啦~_"vue " "^2(1)

cnpm run dev

然后会自动在默认浏览器里打开localhost:8080,里面是系统默认配置的vue版helloworld,大概是这样的:
在这里插入图片描述
显示这个页面,说明已经创建项目成功啦~

暂停当前的vue服务(关闭终端窗口或ctrl+c),安装vuex

npm install vuex --save

在项目文件夹下的package.json文件就会有一个vuex的依赖:

  "dependencies": {
    "vue": "^2.5.11",
    "vuex": "^3.6.2"
  },

表示vuex安装成功,重新使用cnpm run dev启动一下项目

我的小插曲(先记录一下):
        今天安装的时候忽然出了bug,居然提示我找不到vue-cli文件,node_modules目录下的npm文件没了,于是乎,我就又安装了一遍。重点是需要那个npm文件夹,可以找朋友的npm文件复制过来

创建store文件,抽离数据

背景

有时,我们可能在不同组件运用了同一组数据;比如商品的价格,不论是预览还是详情页,该商品的价格是一样的。如果这些组件各自维护这组数据,为保证数据的一致,一旦某个子组件需要改动数据,其他子组件都需要做同样的修改。涉及的组件数量很多时,就变得麻烦易错,且冗余度太高。这时,我们可以通过vuex来管理这组数据
在这里插入图片描述

不使用vuex时,数据是分开维护的

没有用vuex时,组件各自维护自己的数据,就像这样:
主页面App.vue中创建数据

  data () {
    return {
      products:[
            {name:"陕西大苹果",price:120},
            {name:"菠萝",price:12},
            {name:"大西瓜",price:60},
            {name:"百香果",price:20}
          ]
    }
  }

用v-bind动态传递给两个子页面product-list-one和product-list-two:

<template>
  <div id="app">
    <product-list-one v-bind:products="products"></product-list-one>
    <product-list-two v-bind:products="products"></product-list-two>
  </div>
</template>

子页面用props接收后展示

    <ul>
      <li v-for="product in products" v-bind:key="product.id">
            <span class="name">{{product.name}}</span>
            <span class="price">¥{{product.price}}</span>
        </li>
    </ul>

效果
在这里插入图片描述
        是的,我们每个子组件都拿到了父组件传来的数据。如果我们想要修改数据,需要在每个组件中添加一个修改函数saleProducts,这个案例有两个需要修改的组件,就需要添加两次这个函数:

saleProducts(){
  var saleProducts = this.products.map((product)=>{
    return {
      name: product.name+"-onsale",
      price:product.price/2
    }
  })
  return saleProducts
}

效果:这个函数,只为了让商品价格都降一半
在这里插入图片描述
        那可能就有小伙伴在想了,直接在父组件那边修改了数据,然后传给子组件不就好了嘛?欸~我也这么觉得。vuex将这个想法完善成一套机制,用store存储和管理数据,当组件需要这些数据时,去store里取就好了;需要统一修改数据时,也通过提交事件来操作store里的数据。子组件只管取,别的交给vuex

You just move on and I’ll do the rest.
你只管向前,剩下的交给我。

案例修改思路如下:

  1. 转移(剪切)主组件App.vue里的数据,删除主组件v-bind动态传递数据和子组件props接收数据的代码
  2. 新建一个目录存放store代码,包括数据存储、数据获取等
  3. 在main.js文件中引入store文件,并注册到vue实例对象中,此处命名为store
  4. 在子页面使用store,如果仅需要获取源数据,可以使用this.$store.state.数据
    如果在vue对象中注册时命名为x,就写成this.$x.state.数据
  5. 如果需要对源数据做一些过滤、计数操作,可以在getters中进行,如上面说的商品降价,因为此处只是临时降价,不修改源数据,而是拷贝一份出来修改

使用vuex时,数据存储在store中

在src目录下新建文件夹,命名store;里面新键文件,命名store.js,将数据存到这里

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export const store = new Vuex.Store({
    state:{
        products:[
            {name:"陕西大苹果",price:120},
            {name:"菠萝",price:12},
            {name:"大西瓜",price:60},
            {name:"百香果",price:20}
          ]
    }
}
})

在main.js中引入并注册到vue实例中:

import Vue from 'vue'
import App from './App.vue'
import {store} from './store/store.js'

new Vue({
  //将store注册到vue实例中,命名为store
  store:store,
  el: '#app',
  render: h => h(App)
})


在子组件中使用:

computed:{
    products(){
        return this.$store.state.products;
    }
}

<ul>
  <li v-for="product in products" v-bind:key="product.id">
        <span class="name">{{product.name}}</span>
        <span class="price">¥{{product.price}}</span>
    </li>
</ul>

这样就可以正常使用数据products了:

在这里插入图片描述

Take it one step at a time.
一步一步慢慢来。

getters获取数据

源数据可以正常使用后,我们就可以在store里新增getters字段,在这里定义降价函数

getters:{
	// products里的价格都减一半,name加上星星做标记,代表这是降价一半的价格
	saleProducts:(state)=>{
		// map会逐一操作每个元素并返回一个新的对象,不改变源数据
	    var saleProducts = state.products.map((product)=>{
	        return {
	            name: "\*\*"+product.name+"\*\*",
	            price: product.price/2
	        }
	})
    return saleProducts
}

子组件使用降价函数

computed:{
    saleProducts(){
      return this.$store.getters.saleProducts
    }
}

<ul>
  <li v-for="product in saleProducts" v-bind:key="product.id">
        <span class="name">{{product.name}}</span>
        <span class="price">¥{{product.price}}</span>
    </li>
</ul>

效果
在这里插入图片描述
fine,又是this又是$符号的,看起来又高级又简洁(吹牛🤥)

如果我们要真正修改数据,要怎么做呢?

mutations修改数据

摘自官网:
        更改 Vuex 的 store 中的状态的唯一方法是提交mutation
        Vuex 中的 mutation 非常类似于事件:每个 mutation 都有一个字符串的事件类型 (type) 和一个回调函数 (handler)。这个回调函数就是我们实际进行状态更改的地方,并且它会接受 state 作为第一个参数

我们不能随意更改数据,需要使用事件来提交请求,这跟vue里子向父传值需要使用事件传值应该是相似的理念

具体操作如下:

  1. 在store对象里新增mutations字段,定义“价格修改函数”
  2. 在子组件中设置监听
  3. 当某事件发生时,触发处理函数,commit提交修改数据(状态)请求

在store的mutations字段中定义处理函数reducePrice:

mutations:{
    reducePrice:(state)=>{
        state.products.forEach((product)=>{
            product.price -= 1;
        })
    }
}

子组件中commit提交事件请求:

  methods:{
    reducePrice(number){
      this.$store.commit('reducePrice') 
    }
  }

在子组件加一个按钮,绑定点击事件,每次点击按钮时将商品价格减少1

<button @click="reducePrice()">降价</button>

由于数据展示时,会经过上面设置的saleProducts函数——数值降价一半后再显示,我们点击一次按钮,展示时只减了0.5,源数据其实是减了1的,此处都展示出来,做一个对比:

<template>
  <div id="product-list-one">
    <h2>ProductListOne</h2>
    <h3>降价一半后的数据:</h3>
    <ul>
      <li v-for="product in saleProducts" v-bind:key="product.id">
            <span class="name">{{product.name}}</span>
            <span class="price">¥{{product.price}}</span>
        </li>
    </ul>
    
    <h3>源数据在此:</h3>
    <ul>
      <li v-for="product in products" v-bind:key="product.id">
            <span class="name">{{product.name}}</span>
            <span class="price">¥{{product.price}}</span>
        </li>
    </ul>
    <button @click="reducePrice()">降价</button>
  </div>
</template>

效果

在这里插入图片描述
        我们还可以向reduceProducts函数传入参数,比如每次点击按钮降价4元,这个参数,在store有一个专有名:playload

使用处传参:4

<button @click="reducePrice(4)">降价</button>

mutations处接收并处理

打开全栈工匠技能包-1小时轻松掌握SSR

两小时精通jq+bs插件开发

生产环境下如歌部署Node.js

开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】

网易内部VUE自定义插件库NPM集成

谁说前端不用懂安全,XSS跨站脚本的危害

webpack的loader到底是什么样的?两小时带你写一个自己loader

  • 23
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值