Vue教程-day08-2018年12月30日笔记

文章目录

2018年12月30日 - 上午

image-20210912100746261

第141个视频 - tabbar文件路径引用的问题

1 - 上节课路径的问题

image-20210912102209093

上次的代码当中路径没有修改,跑不起来。

2 - 路径起别名

路径层级太深,很麻烦。

在开发当中一般就是要避免这种情况的。

就是要给某些文件夹启别名。

这个也是属于webpack的配置。

image-20210912114528675

以前我们说过,webpack.base.conf.js当中的resolve就是为了解决和路径相关的问题的。

extensions配置的意思就是可以省略某些文件的后缀的。

alias配置就是别名的意思。

现在已经有了一个别名,就是src文件夹的别名是@

如果我们把所有的路径都替换成为@开头的,就可以了。

一般情况下,在项目开发当中,还会搞其他的文件夹的别名。

我们一般就是像下面一样起别名:

image-20210912115029017

3 - 别名需要注意的点

如果你已经起了别名。在vue文件当中的script标签内,import的情况下,使用路径别名是没有问题。

image-20210912115332980

但是在template当中,不是通过import这种方式的,那些资源路径,写上别名还是找不到。

image-20210912115421153

这些路径虽然已经起了别名,但是还是找不到的。

必须都加上波浪符号。

image-20210912115508615

4 - 小问题

我们通过上面的修改之后,重跑了项目,但是出错了。

这个原因是因为这里:

image-20210912115833205

在脚手架2当中,已经配置了@表示src的情况下,配置其他路径的时候,不能够使用@。

在脚手架3当中,是可以的。

我们修改成为下面的配置:

image-20210912115926310

运行效果是正常的:

image-20210912120021709

第142个视频 - Promise的介绍和基本使用

1 - ppt

image-20210912120253215

2 - 同步编程过程

image-20210912121029428

先执行某一段代码,再执行某一段代码。

3 - 异步编程过程

比如网络请求,同步不适合。

用户发送网络请求,网络请求耗时,会阻塞。阻塞用户体验不好。

所以,网络请求,一般都是异步编程过程。

一个网络请求,开启异步任务。程序继续执行。

网络请求数据回来,会通过网络请求的回调函数,拿到网络请求的数据。

  • 网络请求都会开启异步任务。

这是简单的网络请求的过程。

如果网络请求非常复杂,会出现回调地狱。

4 - 回调地狱

回调函数里面又需要回调,多层嵌套回调,这个就是回调地狱。

image-20210912120640815

为了希望使用更加优雅的方式,来进行异步操作,就是使用Promise。

Promise就是对异步操作进行优雅封装。

Promise是一个类。

5 - 为了了解Promise,我们模拟异步操作

image-20210912120646791

Promise是一个类。

我们需要new Promise()来创建对象。

这个时候是需要传入参数的。

我们可以看源码:

image-20210912123351498

创建对象的时候,就是要执行上面的操作。

  • 对象这个参数本身,是一个函数。

  • 这个函数本身包含两个参数,一个叫做resolve,一个叫做reject。

  • resolve和reject本身也是函数。

  new Promise((resolve, reject) => {
    
  });

我们以后所有的异步操作,都放到这个箭头函数的代码块当中。

image-20210912130154161

现在使用Promise之后,逻辑变得很清晰了。即使有十次,代码也很清晰的。

一种是嵌套结构,一种是链式结构。

6 - Promise到底是怎么运行的呢?

什么情况下,会用到Promise呢?

当我们进行异步操作的时候。

一旦进行异步操作,就塞到Promise对象当中,调用resolve()和then()就可以了。

使用Promise对异步操作进行封装。

我们看看Promise的源码:

image-20210912130938229

在接口当中有new的方法。

image-20210912131124928

在我们通过new创建Promise对象的时候,就是执行上面的代码。

当我们创建完成Promise对象的时候,就会回调executor函数。传入两个参数,resolve和reject,这两个也是函数。

在我们通过new创建Promise对象的时候,会执行构造函数。

  • 保存了一些状态信息。
  • 执行传入的函数。
  • 执行函数的时候,传入两个参数,resolve和reject。
  • 之后,我们就可以做异步操作了。
  new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve('冀蕊')
      reject('错误信息')
    },1000)
  }).then((data) => {
    console.log(data);
  }).catch((err)  => {
    console.log(err);
  })

我们在上面的代码当中setTimeout模拟的就是网络请求。

  • 如果网络请求成功,通过resolve来传递请求成功的数据,通过then函数来处理。
  • 如果网络请求失败,通过reject来传递失败的信息,通过catch函数来捕获。

image-20210912120652286

第142个视频 - Promise的三种状态和另外处理方式

1 - PPT

image-20210912120657254

2 - promise的过程

image-20210912140410386

  • async operation是异步操作的意思

  • wrapped into是包裹的意思

  • 意思就是异步操作包裹在Promise当中

    • Pending是等待的状态
    • Fulfilled是满足的意思,意思就是成功了。满足状态就是调用resolve(val)。执行then。
    • rejected就是拒绝失败的意思,一般会有错误信息,失败状态就是调用reject(error),执行catch。
3 - promise的另外的处理方式

我们查看then函数的代码

image-20210912141053667

发现then函数这里可以传入两个参数。

这个参数都是函数。

第一个参数会在fulfilled的时候执行,也就是成功的时候。

第二个参数会在rejected的时候执行,也就是失败的时候。

因此,产生了promise的另外的写法,另外的处理方式:

image-20210912141418821

第143个视频 - Promise的链式调用

1 - ppt

image-20210912120702048

then当中,我们处理完成之后,可以继续返回promise对象。

这样,就可以实现链式调用了。

2 - 链式调用的实例
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
</head>
<body>
<script>
  new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve();
    }, 1000);
  }).then(() => {
    console.log('姜烨烨');
    console.log('姜烨烨');
    console.log('姜烨烨');
    return new Promise((resolve, reject) => {
      setTimeout(() => {
        resolve();
      }, 1000);
    });
  }).then(() => {
    console.log('陈汝莹');
    console.log('陈汝莹');
    console.log('陈汝莹');
    return new Promise((resolve, reject) => {
      setTimeout(() => {
        resolve();
      }, 1000);
    });
  }).then(() => {
    console.log('陈菁华');
    console.log('陈菁华');
    console.log('陈菁华');
  });
</script>
</body>
</html>
3 - 需求 - 不进行异步操作,但是想链式编程
  1. 第一次网络请求,结果是aaa,自己处理(10行)
  2. 处理:给结果aaa拼接111,再自己处理(10行)
  3. 处理:给结果aaa111拼接222,自己处理

这个需求的意思,就是我不想进行异步操作,但是我就是想链式编程的。

我们先实现上面的需求,上面的需求,实现的代码,如下:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
</head>
<body>
<script>
  new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve('aaa');
    }, 1000);
  }).then((res) => {
    console.log(res, '第1层的10行处理代码');
    return new Promise(resolve => {
      resolve(res + '111');
    });
  }).then(res => {
    console.log(res, '第2层的10行处理代码');
    return new Promise(resolve => {
      resolve(res + '222');
    });
  }).then(res => {
    console.log(res + '第3层的10行处理代码');
  });
</script>
</body>
</html>

上面就是,我为了实现一个复杂的需求,我通过使用promise来进行了分布处理。

第一次省略 - 省略了new Promise((resolve) => {resolve()})

如果是这种需求场景下,我们可以简写的。简写的原来如下所示:

image-20210912143410084

上面的写法就是:把第一层的处理结果,通过return Promise.resolve传递给第二层进行处理。

第二次省略 - 省略了Promise.resolve()

但是我觉得这种写法,还是不够简洁。

image-20210912143759518

这样写的时候,内部会自动进行Promise的包装,并且会自动调用resolve()的。

image-20210912120706904

如果某一层出现错误怎么简写

第一次简写:Promise.reject()

image-20210912144612200

第二次简写:throw

image-20210912144709514


第144个视频 - Promise的all方法的使用

1 - 自己实现Promise

自己来实现一个最简单的Promise。

这个王红元没有讲。

2 - 需求场景

我们有多个网络请求,网络请求1和网络请求2。

我们普通情况下,两个网络请求是分别请求的。

但是有一种情况,我们有一个需求,这个需求是需要两个网络请求,只有两个网络请求的数据都拿到的时候,需求才可以实现。

如果我们是使用ajax来发送请求,我们就需要自己手动判断一下,两个网络请求都拿到结果了,然后进行结果处理。

可能的处理方式,是下面的这个样子。

  let isResult1 = false
  let isResult2 = false
  $ajax({
    url: '',
    success: function () {
      console.log('第1个网络请求的结果');
      isResult1 = true
      handlerResult()
    }
  })
  $ajax({
    url: '',
    success: function () {
      console.log('第1个网络请求的结果');
      isResult1 = true
      handlerResult()
    }
  })
  function handlerResult(){
    if (isResult1 && isResult2){
      //处理两次网络请求的结果,进行下一步操作
    }
  }
3 - promise包装两个异步请求

Promise.all()当中是可以传入一个数组,就是一个可迭代对象。

在all()方法内部,会自动判断,两个网络请求都获取到结果的时候,再去then()当中去执行代码。

<script>
  //Promise.all()当中传入iterator可迭代对象
  Promise.all([
      new Promise((resolve, reject) => {
        $ajax({
          url: 'url1',
          success: function () {
            resolve(data)
          }
        })
      }),
      new Promise((resolve, reject) => {
        $ajax({
          url: 'url2',
          success: function () {
            resolve(data)
          }
        })
      })
  ]).then(results => {
    console.log(results[0]);// url1
    console.log(results[1]);// url2
  })
</script>

第145个视频 - vuex概念和作用解析

1 - ppt

image-20210912154518588

  • vuex就是状态管理工具
  • 什么是状态管理呢?
  • 多个组件有一个变量,需要共享。这个变量放到哪里呢?
  • 这些组件之间,不是父子关系,很难联系上。
  • 我们搞个大管家,保存所有需要共享的变量,所有组件都可以朝它要。
    • 这就是所谓的集中式状态管理。
    • 使用vuex管理状态,这个还是响应式的。
    • 响应式就是数据改变,页面改变。
  • 这就是状态管理。
  • 我们可以把这个大管家,想象成为单例对象
2 - 我们自己实现状态管理

如果我们自己来实现这个状态管理器,可以实现吗?

我们可以通过Vue的原型来实现,类似我们在vue-router时候使用 r o u t e r 和 router和 routerroute这种东西。

image-20210912155758163

但是我们上面创建的shareObj并没有放到vue的响应式系统当中。

是无法做到响应式的。

如果你想要封装响应式,又过于麻烦了。

所以vue给你提供了一个vuex。

3 - 开发中什么东西放到vuex中?

只有多个组件需要共享的,放到vuex中。

父组件有个状态,子组件想要用,还是用父子组件通信,不要放到vuex中。

image-20210912154612825

  1. 用户的登录状态
    1. 你去服务器请求数据,有一些数据是只针对登录用户的。
    2. 这个时候请求服务器数据,请求参数必须携带token。
    3. 多个界面请求数据的时候,都需要携带token。
    4. 这个token来自于用户登录成功后,服务器返回给用户的。
    5. 我们可以将token放在vuex当中。
  2. 用户名称
  3. 用户头像
  4. 用户地理位置信息
  5. 商品的收藏
  6. 购物车中的物品

第146个视频 - 单界面到多界面状态管理切换

1 - PPT

image-20210912154632016

2 - 讲一下上面的图

image-20210912170809092

state:状态的意思。状态是用变量保存的。在vue中,变量一般保存在data中。state相当于data中的变量。

state是在view中显示的。

view当中可以产生actions,比如用户发生了点击。

actions反过来会修改state,例如点击的事件函数当中修改data当中的变量。

写代码的话,就是这样的:

image-20210912171138257

image-20210912154642792

3 - 多页面管理

image-20210912154650608

我们现在是要进行多页面状态管理的。

我们新建一个组件叫做HelloVue.vue。

在这个页面当中也展示计数器。

然后注册到我们的App.vue当中。

跑动项目报错:

image-20210912171445844

就是因为我们HelloVue当中没有counter。

但是HelloVue是App的子组件。

我们可以在HelloVue当中定义一个props用来接收父组件传过来的属性。

image-20210912171557872

然后我们在父组件App当中给HelloVue标签 上面绑定属性:

image-20210912171638577

如果两个组件没有直接的父子组件的关系呢?

不希望父子组件通信的方式呢,就需要用vuex。

vuex就是相当于大管家。所有组件的状态都交给vuex。

现在我们有一个counter的状态,想要共享的。

这个可以放到vuex当中。

vuex是一个插件。

我们装的vue原生当中是不包含vuex的。

第一步,安装插件。这个插件是运行时依赖。我们要通过npm安装。

npm install vuex@3.0.1 --save

image-20210912172235831

第二步,我们要为vuex单独创建一个文件夹。我们最好不要在main.js当中写vuex的代码。

之前我们为vue-router创建的文件夹,叫做router。

我们为vuex创建的文件夹,我们一般叫做store。

官网上也是叫做store的。

第三步,在store当中创建index.js。

导入vue和vuex。

  1. 安装插件,使用Vue.use(Vuex),执行这个Vue.use,内部会执行插件的install方法。
  2. 创建store对象,在vuex当中有一个store属性,这个store也是一个类,所以,我们是创建store对象。
  3. 导出store对象,export default store。

image-20210912172730238

  1. 在main.js当中导入store对象,然后挂载到vue实例上面。放到vue实例当中,各个组件才会拿到store对象,才会给我们的vue.prototype设置 s t o r e 属 性 , 然 后 每 个 组 件 都 可 以 通 过 store属性,然后每个组件都可以通过 storestore来获取保存的状态了。

image-20210912172707376

4 - store对象当中放置什么东西呢?

第一个是state,state是一个对象。

第二个是mutations,是一个对象。

第三个就是actions,是一个对象。

第四个就是getters,是一个对象。

第五个就是modules,是一个对象。

5 - state对象

state就是用来保存状态的。我们可以在state当中定义一个状态叫做counter。

image-20210912172913478

我们现在是想要在HelloVue当中使用counter状态。

一旦 store对象在vue实例挂载之后,所有组件都有了$store了。

image-20210912173027022

在App.vue当中,我们在组建内部就不需要维护一个counter变量了,也可以直接使用store对象当中的state当中的counter对象。

image-20210912173132873

image-20210912173217543

现在我们希望点击的时候,counter能够发生改变,但是现在我们点击的时候,直接报错了:

image-20210912173244336

报错的原因,如下图所示:

image-20210912173313525

我们现在点击的时候,要改变的是store当中的state当中的counter。

我们怎么修改呢?

第一种方法,我们直接修改:

image-20210912173354327

得到的效果,如下图所示:

image-20210912173417316

这个效果是正常的。

但是这种修改状态的方法,不好。

为什么不好。

官方不建议这样来进行修改。

官方是建议按照固定的格式来进行修改的。

如果你不按照官方的规定来修改,好像也是可以,但是代码调试的时候,会出现问题的。

6 - vuex状态管理图例

image-20210912154657833

我们看上面的图,虚线部分是属于vuex的。

vue components就是vue的组件。

组件当中能够引用vuex当中的state。

现在如果想要修改state的时候,不要从vue components直接修改。

  • 要先调用一个dispatch,发布一个actions
  • 在actions当中提交comit到mutations
  • 然后通过mutations,mutate修改state
7 - 为什么官方要求这样修改state呢?

上面的图中有一个devtools,这是vue官方提供的浏览器的插件。

这是为vue开发提供的一个插件。

这个插件,可以帮你记录,每次你修改state的状态。

为什么devtools能够记录呢?

我们现在vuex当中管理的状态都是多个页面共享的状态。

修改状态的时候,可能是多个页面都可能修改状态的。

你很难跟踪到到底是哪个页面修改的状态。

不能跟踪

这样你查错的时候,非常难查。

vue官方提供的devtools就可以记录每一次修改state的是哪一个组件。

这样如果出错,就能够定位到组件。

但是,如果你绕过了mutation的环节,你直接从组件修改state,这样devtools就跟踪不到了。

只要是修改state状态,一定要经过mutations,这样devtools才能够跟踪记录,这样调试才容易。

所以结论是:可以从组件当中直接修改state,但是不要这样做,不要这样做。

8 - 图中修改state经过mutations理解,为什么要经过actions呢?

组件修改state,可以隔开actions,直接通过mutations,来修改state,这个是可以的。这个是允许的。

那这个actions是用来干啥的呢?

当你是修改mutations的时候,你有异步操作,不要在mutations当中做。mutations当中推荐的操作就是同步操作。

如果你在mutations当中做了异步操作,这个devtools就跟踪不到了。

如果你有异步操作,你就在actions当中做,等你异步操作完了,你再提交到mutations当中去修改state。

所以,actions是用来做异步操作的。

什么情况下会进行异步操作呢?

就是发送网络请求的时候,所以在官方的图当中,actions后面是连接backend api。

image-20210912174714021

  • 后端:backend
  • 前端:frontend

2018年12月30日 - 下午

第147个视频 - devtools和mutations

1 - 安装devtools

image-20210912175301200

image-20210912175343910

如上图的位置,出现了vue,就表示安装成功了。

点击vue,就是下面的界面:

image-20210912175417634

这个东西,就是做调试用的。

也可以在vue当中看到当前项目的结构的:

image-20210912175452482

这个插件是可以用于调试整个程序的。

当我们的程序比较复杂,有个商品列表,看看商品列表当中的数据,对不对,就可以使用devtools。

之后讲项目的时候,可以使用这个工具。

2 - 切换devtools的vuex

image-20210912175612589

image-20210912175623397

这里会显示你定义的所有数据。

如果你通过mutations修改state,就会在上方显示跟踪。

像是我们直接修改的时候,这个工具就不会生效。

image-20210912175729496

3 - mutations怎么用

我们可以在store文件夹的index.js当中的store对象中的mutations对象中,定义很多方法。

定义的方法,都是修改state的方法。

这些方法都是默认有一个参数的,就是state的。不需要你自己通过this什么去拿state对象中的数据。

我们直接使用mutations方法参数当中的state,就可以了。

我们这样写mutations方法来修改state当中的counter:

image-20210912175936918

在组件当中,我们怎么调用mutations当中的方法呢?

通过下面图中的步骤,在组件当中提交mutations方法:

image-20210912180310999

我们看一下效果:

image-20210912180400452

效果就是上面图的样子。

上面图的右边,我们可以点击filter mutations这个跟踪路径当中每个元素,查看每一次修改的状态。

image-20210912180601440

4 - 这个就是PPT中对我们的简单案例的描述

image-20210912154704570

image-20210912154711902

image-20210912154719045

第148个视频 - state单一状态树的理解

前面我们讲了vuex的基本使用,我们现在讲讲vuex的核心概念

1 - 核心概念

image-20210912154725749

第一个比较核心的概念就是state,这里会引出来state的单一状态树,后面说。

第二个就是getter,类似我们的computed,计算属性。

第三个就是mutations。

第四个就是actions

第五个就是modules,就是划分模块,根据模块进行相关数据保存。

vuex除了基本使用,还有五个核心概念。我们一一介绍。

2 - state概念

state就是用来放置状态信息的。非常简单。

但是state当中,vuex讲state的时候,讲到了一个概念,就是单一状态树。

这个名字高大上,什么意思呢?

image-20210912154731880

我们直接翻译过来,单一状态树,就是单一数据源。

我们国家中,每个人的个人信息都是记录下来的。你的档案、社保记录、公积金、结婚、户口、医疗、房产都需要记录。

目前我们国家都是分类在不同部门不同系统进行记录的。

如果很多信息分布不同系统,好处就是每个信息划分比较清晰,还有一个就是比较数据安全。

如果某一天系统被入侵了,信息暴露了,只有这一个系统,其他系统相对安全。这个是优势。

划分清晰,可以提供比较多的就业岗位。

但是这种信息管理,有很多缺点,比如说你要办理某个业务,比如说你要入户,你会发现,你要提交很多信息,你要去不同部门打印不同信息。

然后每个地方都需要盖章,然后你最终把所有信息提交某个地方,你就可以入户了。

信息的分布的坏处,办理业务的时候,非常麻烦,而且低效。

在我们国家肯定有一个系统,可以查到一个人所有的信息的。

比如公积金,你杭州工作,然后深圳,然后去北京,公积金账户不是同一个。你就要到处跑。非常麻烦。

我们国家现在正在不断完善这些系统。比如公积金系统。

举这个例子告诉大家,跟我们开发比较类似。

vue在设计vuex的时候,提出来单一状态树的概念。

我们当前创建了一个store对象。我们能够创建多个吗?创建多个store对象然后分类存储信息。

vue的单一状态树的意思就是,别这样,你最好是使用一个store对象。

你的所有的状态信息,统一放在一个store对象,就可以了,这个就是单一状态树的概念内涵。

不推荐你在项目当中搞很多的store。

单一状态树,你能够非常直接找到你的状态信息,方便维护和调试。

在一个项目当中,不要建多个store,永远用一个store,对应每个组件当中的$store。

第149个视频 - getters的使用详解

vuex有五个核心:state、getters、mutations、actions、modules。

getters在开发当中,也是用得比较多,类似于组件当中的计算属性computed。

计算属性是在什么条件下使用呢?

当我们某个数据必须经过一系列变化,再让界面使用的时候,就可以通过计算属性了。

getters也是一样。

比如说,我们想要从state当中获取状态counter的时候,我们希望对counter经过某种变化之后再进行获取。

这个时候,就可以使用getters。

1 - 演示一下getters

image-20210912182433829

我们在getters当中也是写方法,方法也是有个默认的参数,就是state对象的。

image-20210912182519843

在store对象当中,我们就像上面的写法,写getters,在组件当中,我们这样使用:

image-20210912182609939

效果如下:

image-20210912182647302

这个就是getters最基本的使用。

2 - ppt中演示的getters基本使用

image-20210912154738162

我们在代码当中演练一下ppt当中的案例:

image-20210912183028139

定义了这些state,某个组件当中想要获取年龄大于20岁的学生。

我们可以怎么做呢?

第一种做法。

我们在组件当中搞一个计算属性。

image-20210912183311939

filter函数的作用是:针对students数组,会拿到数组当中的每个对象,就是s,返回值是一个表达式,如果表达式是false的时候,就会忽略掉,如果表示是true的时候,就会将这个对象,添加到新的数组当中进行返回。

我们可以再优化一下,使用箭头函数的简写 形式:

image-20210912183523074

效果如下:

image-20210912183542524

这个就是一种实现方法。

但是假如说,其他组件当中也想要获取年龄大于20岁的学生呢?就也需要在组件当中写计算属性。

所以,这个时候,我们最好的做法,是写到getters当中。

第二种实现方法,就是使用getters。

image-20210912183700540

我们组件当中直接使用就可以了:

image-20210912183725587

上面的就是ppt当中讲解的getters基本使用的案例,我们又用代码写了一遍。

3 - getter的传参

需求场景是:不仅仅是想要获取年龄大于20岁的学生,还想要获取年龄大于20岁学生的个数。

这个时候怎么办呢?

我们可以直接在组件当中进行获取。

image-20210912183905115

但是我们的需求要求,把获取个数的这个方式,定义成为一个store的getter。

我们怎么做呢?

image-20210912184015930

我们可以通过上面的方式,直接实现。

但是这种写法,有点啰嗦。

我们可以通过在getters当中进行传参,传入一个getters对象。

image-20210912184142186

4 - 更复杂的东西

需求场景:想要获取年龄大于age的学生,age是别人用getters的时候,传进来的。

image-20210912184312361

这个时候,我们怎么写getters呢?

image-20210912184439108

不要再getters的参数上想办法了。

我们的getters可以返回一个函数给调用方。

这个调用处就是一个函数,就可以进行传参了。

image-20210912184808299

如果你的getters想要别人传参的情况下,你的getters就要返回一个函数。

当然了上面的代码, 你也可以用箭头函数来进行优化得更加简洁:

image-20210912185007483

第150个视频 - mutations的携带参数

1 - PPT

image-20210912154752432

mutations当中定义的函数,可以看成两部分。一个叫做字符串的事件类型,一个叫做回调函数。

知道这个东西有什么用呢?待会就会用到的。

函数当中的第一个参数就是state对象。

通过mutation更新就是根据$store来commit事件类型了。

2 - commit mutations的时候传入参数

我们希望点击按钮,给counter这个状态加5和加10。

我们在组件当中定义一个方法:

image-20210912185544450

这个方法是可以传入参数的。

image-20210912185735536

所以,我们在我们的store对象当中,去mutations当中去定义一个方法。

image-20210912185854264

效果是正常的:

image-20210912185917168

这个也就是说明,我们在组件当中通过$store对象进行commit的时候,我们就可以通过这种方式来实现就可以了。

3 - commit mutations的时候传入多个参数

我们在组件当中添加一个按钮,如果点击按钮的时候,就往store的state当中增加一个学生对象。

这种情况,就不能够传入一个参数了,就是传入一个对象。

1、组件内的按钮:

image-20210912190330087

2、组件内的方法:

image-20210912190434805

3、store对象当中的mutations中的方法:

image-20210912190513295

这个如果有多个参数需要传递的时候,我们就放到一个对象当中进行传递就可以了。

在store的mutations当中,我们传入的参数,这个参数叫做payload,叫做载荷。

4 - ppt当中的讲解

image-20210912154759263

第151个视频 - mutation的提交风格

之前的提交风格,就是通过$store的commit方法,就可以进行提交了。

vuex还提供了另外的提交风格,就是可以把所有提交的东西,都放置在一个对象当中。

1 - 普通的提交风格

image-20210912190852759

2 - 特殊的提交风格

image-20210912191027477

我们使用这种风格去提交的时候,在store的mutations的方法中,就不像是普通提交风格中,直接拿到参数了。

而是拿到一个对象。

在mutations当中的方法中,我们要执行的操作,就需要通过对象来实现:

image-20210912191459457

3 - ppt中对mutation提交风格的表述

image-20210912154805351

第152个视频 - 数据的响应式原理

1 - ppt

image-20210912154811543

store对象的state响应式,是有一定的要求的。

第一个规则:提前在store当中要初始化的数据,初始化好。

image-20210913125137507

在store/index.js当中store中定义一个info:

image-20210913125239066

在App.vue当中,template当中展示store当中的state信息:

image-20210913124658674

在App.vue当中,写一个监听点击的函数:

image-20210913124330571

在store/index.js中mutations中写一个方法:

image-20210913124511573

效果:

image-20210913125520554

我们创建state的时候,初始化了一个info,初始化了之后,就会加入到vue的响应式系统当中,vue就会通过一个watcher的东西,就可以观察到这些数据的变化,然后就可以响应式渲染了。

每一个info的属性都有一个Dep,通过Dep对应好多watcher。

我们在info当中有3个属性,每个属性都对应一个Dep对象,Dep是一个观察者模式,可以监听属性的数据变化,会看一下哪些地方是需要根据数据变化发生更新的。Dep里面有一个数据,每个数组都有一个watcher,每个watcher对应页面上的内容。

记住:这些属性一开始定义到state当中,初始化好了,就会被加入到响应式系统当中。

反例

假如,我们在上面,通过按钮,修改我们的state,给info对象,新增一个address属性和值,这个不会加入到响应式系统当中。

需求

在开发当中,我们给state新增一个属性。我们确实是想要它加入到响应式系统当中的。

我们怎么办呢?

有没有办法解决呢?

之前我们讲数组的时候,讲到了哪些方法是响应式的,讲了push方法,pop方法,shift方法,unshift方法,splice方法,sort方法。

image-20210913130717072

看上面的图,我们通过Vue.set,就可以加入到响应式中。

在state当中,也是一样的。

image-20210913130904125

通过Vue.set追加state的时候,就可以加入到响应式系统中了。

除了vue.set还有其他吗?

我们不要给state当中的info对象追加属性。

我们想要删除state当中info对象的属性。

image-20210913131137006

效果如下:

image-20210913131221236

我们通过devtools可以看到age被删除了,但是页面,并没有响应式。

所以,使用delete删除对象属性,也做不到响应式。

对应的,有一个Vue.delete方法。

image-20210913131341463

这样写了之后,就可以使删除操作变成响应式了。

总结

1 - 原来定义的属性,可以响应式

2 - 追加对象属性,使用vue.set

3 - 删除对象属性,使用vue.delete


第153个视频 - mutations的类型常量

1 - 讲解

我们当前的mutations中已经定义了很多个方法。

image-20210914123327513

我们之前在mutations中定义了一个方法,然后在组件的methods中通过this.$store.commit的时候,就是拷贝mutations中方法的名字。

如上面的图所示,但是有的人不喜欢拷贝,有的人就喜欢手写。

vuex也考虑了这个问题。

我们使用常量来解决这些问题。

第一,搞一个文件mutations-types.js,然后在文件中,这样写:

image-20210914123717102

然后,我们需要在组件中,进行mutations提交的时候,我们导入mutations-types.js当中的常量。

我们在上面是使用export const来导出了一个常量。

那么我们在组件中,应该用什么方式导入呢?

import INCREMENT from ./store/mutations-types这种方式可以吗?

是不可以的。

什么情况下才可以使用import from这种方式呢?

这种方式就是相当于自己在起名字。

只有导出的方式是export default的时候。

普通导出的方式,在导入的时候,只能够写大括号。就是下面的这种方式。

image-20210914124238193

这样,在methods当中,提交mutations的时候,写方法事件的时候,我们就可以使用下面的方式:

image-20210914124323306

这个常量,我们怎么能够在./store/index.js当中,也使用呢?

第一个,当然也是按照上面的方式,来进行导入的。

第二个,在./store/index.js当中的mutations当中的方法,是可以写成下面的格式的:

image-20210914124508823

官方网站推荐我们在写mutations的时候,就是通过这种方式。

2 - ppt

image-20210912154818858

image-20210912154825688

第154个视频 - vuex-actions的使用详解

image-20210912154831792

给大家演示一个东西。

第一步:我们看看有一个修改state当中对象属性的方法:

image-20210924201819979

第二步,这种操作肯定是响应式的,因为我们在state当中定义这各info对象的时候,已经是初始化了之后的。

image-20210924201901961

第三步,看看效果。

我们点击了按钮,触发了事件函数,然后看看,确实是响应式的:

image-20210924201944848

我们通过上面三步做了一个小小的演示。

这种修改就是一个同步的操作。

问题:假如我们不用同步的修改,我们使用异步的修改呢?

第一步:代码修改:

image-20210924202036929

第二步:看看效果。

image-20210924202113024

第三步:疑问?

image-20210924202153573

我们的devtools当中,还是kobe,没有修改掉的。

这个就是问题。

这个就不利于调试。

这个就让devtools失效了。

不能够跟踪了。

这个info对象已经发生变化了,这个devtools跟踪不到了。

解释

为什么会出现这种状况呢?

在mutations当中进行异步操作,就是有这个弊端,页面上没有什么错误,但是devtools当中没有实时更新和记录。

vue官网推荐我们,不要在mutations当中进行异步的操作,不然的话,devtools就失效了。

结论

如果确实想要做异步操作的时候,就用action。

如果你没有异步操作,就用mutations。组件当中是可以直接提交mutations的。

如果提交的时候,还有异步操作,就必须放到actions当中。

例如网络请求的这些东西。

actions是类似于mutations,是进行异步操作的。

基本讲解

image-20210924202809843

如果有异步操作的时候,就写到actions当中。mutations当中函数方法,都有默认的参数叫做state。

actions当中有默认的参数,叫做context,这个context可以就是理解成为store对象。

我们在actions当中定义一个方法,然后在这里写方法来进行异步操作。

我们可以在actions的方法当中,直接修改state吗?

当然是不可以的。

我们官方文档已经说过了,修改state的唯一的途径,就是通过mutations的。

我们不能够在actions当中直接来修改state的。

这个一定要记住的。

image-20210924203153755

如果是异步想要修改的时候,必须像是下面的做法。

正确的异步修改state方法

image-20210924203319418

我们原来是通过按钮来修改state当中的对象属性。

  • 点击按钮
  • 执行按钮当中的事件函数
  • 事件函数当中执行this.$store.commit()
  • commit当中写的是mutations当中的方法的名字。

现在我们是通过actions来提交了commit,我们的正确的业务实现的顺序,应该是这样的。

  • 点击按钮
  • 执行按钮当中的事件函数。
  • 事件函数当中执行this.$store.dispatch
  • 为什么是dispatch请看下面的图

image-20210924203611419

  • 然后在dispatch()当中写的是actions当中方法的名字。
  • actions的方法当中写的是commit
  • commit当中写的mutations当中的方法的名字
  • 执行mutations当中的方法,修改了state。

看看效果:异步操作的效果,是正常的。

image-20210924203739869

第二个问题,mutations能够传递参数,actions可以吗

肯定是可以的。

第一步,actions当中的方法使用payload来承接。

image-20210924203848600

第二步,dispatch的时候,是可以传参的。

image-20210924203914513

第三步,看看效果。

image-20210924203953162

讲第二个东西:actions异步改state要不要告诉外面已经修改成功

actions当中是异步操作,actions当中是进行了commit,commit到了mutations当中,mutations来执行真正的修改的动作。

  • 你需要通知页面,组件,已经修改成功了。

  • 组件说:我知道了,你通知了我之后,我要做一点其他的操作。

  • 那么我们怎么做?

  • 第一步:怎么判断什么时候修改成功呢?

    • 一般认为actions当中commit了,就是修改成功了。
  • 第二步,我们需要在commit了之后回调。

  • 第三步,我们怎么做呢?

    • image-20210924204457676
    • image-20210924204518201

这种方案的意思,就是我们在事件函数当中调用actions的方法的时候,dispatch的时候,我们传参进去一个函数。

然后我们在actions方法内部,如果是已经修改成功了,就是commit了之后,就调用参数当中函数,进行回调。

回调的效果检验

image-20210924204704644

这样写,有另外的问题,就是我既需要传参,也需要回调的时候,咋整?!!!!

既要回调,也要传参的情况

传统解决方法:

第一步:组件调用,进行传参的时候,传入一个对象:

image-20210924204916548

第二步:在actions的方法当中,直接通过对象来获取参数和回调函数就可以了。

image-20210924204944673

问题: 上面的做法不够优雅

携带的信息和回调的方法是耦合的,是放在一起的。

所以我们要用一种更加优雅的方式来做这种事情的。

第一步:组件当中调用$store.dispatch的时候还是正常地传参。然后在actions当中进行commit的时候还是正常地commit。

image-20210924230855962

image-20210924231210374

第二步,现在是想要用一种优雅地方式,在commit之后,回调给组件调用的地方。

image-20210924231636820

image-20210924231735597

我们是在actions当中返回了一个promise对象。

然后是在组件的事件函数当中写了一个then。

ppt

image-20210912154838536

image-20210912154844926

image-20210912154850590

第156个视频 - vuex-modules的使用详解

如果我们将所有的状态,往一个state对象当中塞,就会造成这个state比较臃肿。

image-20210924232428639

而我们现在推荐单一状态树。又意味着,你只能够创建一个state。

其实vuex后来也考虑到了这个问题。

它建议你可以在store当中具体分模块

image-20210924233914332

vue官网推荐,当你有一些东西,单独做一些抽离的时候,可以继续定义我们的模块。

看一下笔记

image-20210912154857902

做一点演练

image-20210925002111674

我们定义了一个moduleA,然后我们在moduleA当中设置一些状态。

image-20210925002331479

我们定义了一个名字,叫做zhangsan。

第三步,我们在页面当中进行演示。

image-20210925002530463

image-20210925002548558

通过上面的两张图,我们知道modules当中的玩意,最后都会放到state当中的。看一下第一张图当中的a的object。

所以,第三步当中,我们在页面当中进行展示的时候,是这样来获取的:

image-20210925002650135

第四步,看一下结果:

image-20210925002716950

结果是正确的。


模块当中的mutations

第一步,在模块当中我们写一个updateName方法

image-20210925002825071

第二步,我们在页面当中,写一个button,绑定一个事件函数,然后在函数当中,我们应该进行commit。

image-20210925002905445

image-20210925003034992

注意,虽然我们的mutations是定义在模块当中的,但是我们提交的时候,还是正常地提交,一般情况下会先去store对象的mutations当中去寻找,有没有对应的方法,如果没有的话,就会去模块当中的mutations当中去寻找对应的方法的。

注意,我们直接写在state对象当中的mutations方法,和我们直接在模块当中写的mutations方法,一般情况下,一般情况下,方法的名字是不要重复的哦。

第三步,验证效果

image-20210925003238276

点击按钮,修改名字之后,就是下面的状态:

image-20210925003334359

模块当中的getters

第一步,我们在模块当中定义一个getter

image-20210925003440913

第二步,我们在组件当中获取一下子。

这个getter也是不关心,你是定义在state对象当中的,还是定义在模块当中的。

image-20210925003533191

即使你是把fullname定义在模块当中,在使用的时候,也是跟之前一样的。

第三步,看看结果:

image-20210925003603775

模块当中的getter第二个问题

我们之前在讲getter的时候,遇到这样的一个情况,就是其中一个getter想要用另外的一个getter,这个时候就是这个样子的:

image-20210925003749329

那么在模块的getter当中呢?

如果是出现了类似上面的情况,怎么办呢?

image-20210925003849975

然后直接用一下:

image-20210925003909238

然后我们看一下效果:

image-20210925003926664

说明,在module当中也是可以这样用的。

模块当中的getter想要使用store对象当中的state

在模块的getter当中,第一个参数是state,第二个参数是getters,第三个参数是rootState。

image-20210925004123298

第二步,我们来使用一下子。

image-20210925004143830

第三步,我们来看一下效果:

image-20210925004158697

模块当中的actions

actions就是进行一些异步操作。

第一步,我们在actions当中写一个方法,actions当中的方法,有一个参数,叫做context。

在模块当中的,actions当中的,方法的参数,context参数,这个就不是store对象了。

在store对象当中的,actions当中的,方法的参数,context参数,这个就是store对象。

store对象的commit,就是我们store对象当中,直接写的mutations。

但是我们模块当中的actions当中的context,只有commit到模块自己的mutations当中的。

image-20210925004717025

上面的这是第一步。

第二步,我们在组件当中设置一个按钮。

image-20210925004801496

第三步,我们在组件的methods当中定义一个事件的方法:

image-20210925004835304

效果:

image-20210925004908434

点击了按钮之后,异步修改名字:

image-20210925004924985

模块当中的actions当中的context就会提交到模块当中的mutations当中的。

我们可以打印一下context对象。

image-20210925005032792

image-20210925005102255

从上面我们可以看到从context当中拿到rootGetters,从context当中拿到rootState。

讲到这里就讲完了模块。

第157个视频 - vuex-store文件夹的目录组织

先看看PPT

image-20210912154903527

image-20210912154910032

image-20210925005331580

本来我们应该写一个context对象的,但是我们可以利用对象的结构语法,写成上面的样子。

对象的结构

第一步,定义一个对象。

第二步,将对象当中的属性,一一取出。

传统的写法是这样的:

image-20210925005442312

es6当中的解构写法是比较简单的,是这样的:

image-20210925005508487

而且大括号当中的,name,age,height这些顺序是可以换的。

image-20210925005536856

回去看actions的写法

image-20210925005606499

context当中有很多的属性,但是我们用对象的解构的写法,取出来三个属性,就是state,commit,rootState。

vuex-store项目的结构

image-20210912154916285

我们现在vuex相关的代码,都是写到了index.js当中的。

代码有点乱的。

不方便管理。

vuex推荐我们以某种目录结构来组织代码。

其实就是代码抽离。

下面我们来重构一下代码。

第一步,我们将store对象当中的state当中的代码,剪掉。

image-20210925005947868

第二步,我们放到store对象外面:

image-20210925010008859

第三步,修改store对象当中的state:

image-20210925010037875

这是es6的对象属性字面量增强写法。

mutations可能你也是想要用上面的抽取的方式。

但是vuex是不推荐mutations这样做的。

推荐的做法

store对象是在index.js当中的。

  • state当中的代码,是推荐放在index.js当中的。做一个对象抽离。
  • mutations当中的代码是推荐你搞一个文件。

image-20210925010257919

image-20210925010422411

actions也是同样的做法。

getters也是同样的做法。

modules推荐的做法

推荐建一个modules文件夹。

在文件夹里面创建一个js文件,就是modulesA.js

image-20210925010736305

如果是多个模块的话,就都可以放在文件夹里面进行管理了。

总结

经过上面的代码抽取。代码就变得非常整洁。

state为什么不抽取呢?

因为state是整个vuex的状态,一般是不抽取的。

灵活一点。

mutations、actions、getters、modules这些东西都会抽取的。

到这里,第8天的课程就结束了。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值