精华内容
下载资源
问答
  • 1. 前言大家好,我是若川。好久以前我有写过《面试官问系列》,旨在帮助读者提升JS基础知识,包含new、call、apply、this、继承相关知识。其中写了 面试官问:this 指向 文...

    1. 前言

    大家好,我是若川。好久以前我有写过《面试官问系列》,旨在帮助读者提升JS基础知识,包含new、call、apply、this、继承相关知识。其中写了 面试官问:this 指向 文章。在掘金等平台收获了还算不错的反馈。

    最近有小伙伴看我的 Vuex源码 文章,提到有一处this指向有点看不懂(好不容易终于有人看我的源码文章了,感动的要流泪了^_^)。于是我写篇文章答疑解惑,简单再说说 this 指向和尤大在 Vuex 源码中是怎么处理 this 指向丢失的。

    2. 对象中的this指向

    var person = {
      name: '若川',
      say: function(text){
        console.log(this.name + ', ' + text);
      }
    }
    console.log(person.name);
    console.log(person.say('在写文章')); // 若川, 在写文章
    var say = person.say;
    say('在写文章'); // 这里的this指向就丢失了,指向window了。(非严格模式)
    

    3. 类中的this指向

    3.1 ES5

    // ES5
    var Person = function(){
      this.name = '若川';
    }
    Person.prototype.say = function(text){
      console.log(this.name + ', ' + text);
    }
    var person = new Person();
    console.log(person.name); // 若川
    console.log(person.say('在写文章'));
    var say = person.say;
    say('在写文章'); // 这里的this指向就丢失了,指向 window 了。
    

    3.2 ES6

    // ES6
    class Person{
      construcor(name = '若川'){
         this.name = name;
      }
      say(text){
        console.log(`${this.name}, ${text}`);
      }
    }
    const person = new Person();
    person.say('在写文章')
    // 解构
    const { say } = person;
    say('在写文章'); // 报错 this ,因为ES6 默认启用严格模式,严格模式下指向 undefined
    

    4. 尤大在Vuex源码中是怎么处理的

    先看代码

    class Store{
      constructor(options = {}){
         this._actions = Object.create(null);
      // bind commit and dispatch to self
          // 给自己 绑定 commit 和 dispatch
          const store = this
          const { dispatch, commit } = this
          // 为何要这样绑定 ?
          // 说明调用commit和dispach 的 this 不一定是 store 实例
          // 这是确保这两个函数里的this是store实例
          this.dispatch = function boundDispatch (type, payload) {
            return dispatch.call(store, type, payload)
          }
          this.commit = function boundCommit (type, payload, options) {
            return commit.call(store, type, payload, options)
          }
      }
      dispatch(){
         console.log('dispatch', this);
      }
      commit(){
         console.log('commit', this);
      }
    }
    const store = new Store();
    store.dispatch(); // 输出结果 this 是什么呢?
    
    const { dispatch, commit } = store;
    dispatch(); // 输出结果 this 是什么呢?
    commit();  // 输出结果 this 是什么呢?
    
    输出结果截图

    结论:非常巧妙的用了calldispatchcommit函数的this指向强制绑定到store实例对象上。如果不这么绑定就报错了。

    4.1 actions 解构 store

    其实Vuex源码里就有上面解构const { dispatch, commit } = store;的写法。想想我们平时是如何写actions的。actions中自定义函数的第一个参数其实就是 store 实例。

    这时我们翻看下actions文档https://vuex.vuejs.org/zh/guide/actions.html

    const store = new Vuex.Store({
      state: {
        count: 0
      },
      mutations: {
        increment (state) {
          state.count++
        }
      },
      actions: {
        increment (context) {
          context.commit('increment')
        }
      }
    })
    

    也可以用解构赋值的写法。

    actions: {
      increment ({ commit }) {
        commit('increment')
      }
    }
    

    有了Vuex源码构造函数里的call绑定,这样this指向就被修正啦~不得不说祖师爷就是厉害。这一招,大家可以免费学走~

    接着我们带着问题,为啥上文中的context就是store实例,有dispatchcommit这些方法呢。继续往下看。

    4.2 为什么 actions 对象里的自定义函数 第一个参数就是 store 实例。

    以下是简单源码,有缩减,感兴趣的可以看我的文章 Vuex 源码文章

    class Store{
     construcor(){
        // 初始化 根模块
        // 并且也递归的注册所有子模块
        // 并且收集所有模块的 getters 放在 this._wrappedGetters 里面
        installModule(this, state, [], this._modules.root)
     }
    }
    

    接着我们看installModule函数中的遍历注册 actions 实现

    function installModule (store, rootState, path, module, hot) {
        // 省略若干代码
        // 循环遍历注册 action
        module.forEachAction((action, key) => {
          const type = action.root ? key : namespace + key
          const handler = action.handler || action
          registerAction(store, type, handler, local)
        })
    }
    

    接着看注册 actions 函数实现 registerAction

    /**
    * 注册 mutation
    * @param {Object} store 对象
    * @param {String} type 类型
    * @param {Function} handler 用户自定义的函数
    * @param {Object} local local 对象
    */
    function registerAction (store, type, handler, local) {
      const entry = store._actions[type] || (store._actions[type] = [])
      // payload 是actions函数的第二个参数
      entry.push(function wrappedActionHandler (payload) {
        /**
         * 也就是为什么用户定义的actions中的函数第一个参数有
         *  { dispatch, commit, getters, state, rootGetters, rootState } 的原因
         * actions: {
         *    checkout ({ commit, state }, products) {
         *        console.log(commit, state);
         *    }
         * }
         */
        let res = handler.call(store, {
          dispatch: local.dispatch,
          commit: local.commit,
          getters: local.getters,
          state: local.state,
          rootGetters: store.getters,
          rootState: store.state
        }, payload)
        // 源码有删减
    }
    

    比较容易发现调用顺序是 new Store() => installModule(this) => registerAction(store) => let res = handler.call(store)

    其中handler 就是 用户自定义的函数,也就是对应上文的例子increment函数。store实例对象一路往下传递,到handler执行时,也是用了call函数,强制绑定了第一个参数是store实例对象。

    actions: {
      increment ({ commit }) {
        commit('increment')
      }
    }
    

    这也就是为什么 actions 对象中的自定义函数的第一个参数是 store 对象实例了。

    好啦,文章到这里就基本写完啦~相对简短一些。应该也比较好理解。

    最后再总结下 this 指向

    摘抄下面试官问:this 指向文章结尾。

    如果要判断一个运行中函数的 this 绑定, 就需要找到这个函数的直接调用位置。找到之后 就可以顺序应用下面这四条规则来判断 this 的绑定对象。

    1. new 调用:绑定到新创建的对象,注意:显示return函数或对象,返回值不是新创建的对象,而是显式返回的函数或对象。

    2. call 或者 apply( 或者 bind) 调用:严格模式下,绑定到指定的第一个参数。非严格模式下,nullundefined,指向全局对象(浏览器中是window),其余值指向被new Object()包装的对象。

    3. 对象上的函数调用:绑定到那个对象。

    4. 普通函数调用:在严格模式下绑定到 undefined,否则绑定到全局对象。

    ES6 中的箭头函数:不会使用上文的四条标准的绑定规则, 而是根据当前的词法作用域来决定this, 具体来说, 箭头函数会继承外层函数,调用的 this 绑定( 无论 this 绑定到什么),没有外层函数,则是绑定到全局对象(浏览器中是window)。这其实和 ES6 之前代码中的 self = this 机制一样。


    最近组建了一个江西人的前端交流群,如果你是江西人可以加我微信 ruochuan12 私信 江西 拉你进群。


    推荐阅读

    我在阿里招前端,该怎么帮你(可进面试群)
    我读源码的经历

    在字节做前端一年后,有啥收获~
    老姚浅谈:怎么学JavaScript?

    ················· 若川简介 ·················

    你好,我是若川,毕业于江西高校。现在是一名前端开发“工程师”。写有《学习源码整体架构系列》多篇,在知乎、掘金收获超百万阅读。
    从2014年起,每年都会写一篇年度总结,已经写了7篇,点击查看年度总结
    同时,活跃在知乎@若川,掘金@若川。致力于分享前端开发经验,愿景:帮助5年内前端人走向前列。

    识别方二维码加我微信、长期交流学习

    今日话题

    略。欢迎分享、收藏、点赞、在看我的公众号文章~

    展开全文
  • 1. App.vue const ret = await this.$store.dispatch('userLogin', { username: this.curUserName, password: this.curPassword }) if (ret &&...

    1. App.vue

    •         const ret = await this.$store.dispatch('userLogin', {
                username: this.curUserName,
                password: this.curPassword
              })
              if (ret && ret.info) {
                this.$message.success(ret.info)
                await this.$store.dispatch('controlLoginDialog', false)
              } else {
                this.$message.warning(ret)
              }

    2. vuex/store/action.js

    •   async userLogin ({commit}, account) {
          let userInfo = {}
          return new Promise((resolve, reject) => {
            requestUserLogin(account).then(response => {
              if (response.status === 200) {
                if (response.data.data) {
                  userInfo = response.data.data
                  userInfo.userName = userInfo.name
                  userInfo.isLogin = true
                  resolve({
                    info: userInfo.userName + ' 登录成功,欢迎进入百度云智学院实验平台'
                  })
                } else if (response.data.fail) {
                  userInfo.userName = ''
                  userInfo.isLogin = false
                  myConsole('response.data.fail')
                  resolve(response.data.fail)
                }
              } else {
                userInfo.userName = ''
                userInfo.isLogin = false
              }
      
              commit(USER_LOGIN, {userInfo})
            }).catch(err => {
              myConsole(err)
              reject(err)
            })
          })
        },

    3. 

    转载于:https://www.cnblogs.com/tianxiaxuange/p/10940222.html

    展开全文
  • vuex中访问vue实例

    2021-06-16 10:17:48
    vuex中访问vue实例 vue项目使用vuex,在vuex的Actionsthis指向Vuex实例。在this下有一个this._vm,它就是Vue实例,可以使用挂载在vue原型上的方法。

    在vuex中访问vue实例

    vue项目中使用vuex,在vuex的Actions中,this指向Vuex实例。在this下有一个this._vm,它就是Vue实例,可以使用挂载在vue原型上的方法。

    展开全文
  • window.vue = new Vue({ router, render: h => h(App) }).$mount('#app')
    window.vue = new Vue({
      router,
      render: h => h(App)
    }).$mount('#app')
    
    
    展开全文
  • VueX中使用axios

    千次阅读 2019-05-14 10:38:05
    在学习某课网模仿美团的视频,在安装时nuxt会出现无法安装@/nuxt/axios的情况,而在vuex中无法直接调用axios,因为this无法指向vue,所以我找了几种比较好的方法来解决这个问题,因为这些文章大概内容都差不多,我...
  • 有时候我们在使用vue的过滤器filters方法时,用到this时会报undefined错,那是因为在filtersthis指向其实是为undefined,如果真的想使用可以全局定义一个that, 进行代替,let that = this; 那是因为当初为了...
  • vuex中获取state数据

    万次阅读 2018-06-06 16:01:06
    在vue项目引用了vuex,管理共享状态1.安装vuex npm i vuex --save...注意事项:如果vue引用了jquery,在jq函数调用 this.$store.state可能会报错,state undefined,尽量不要写在jq函数,可能是this指向不对...
  • 在VUE项目,我们想把一些主要的代码抽到一个模块 ... // 这里的this指向的是当前的对象,我们一般想要的是VUE实例的this } } 有两种方法, 方法一, 在调用这个方法的时候把this传进来,但是假如...
  • Vuex中的Mutation

    2021-07-27 15:29:09
    Mutation的作用? 用于变更Store的数据 。 如何使用Mutation? const store = new Vuex.Store({ state : { count : 0 }, ... xxx(state){ //xxx代表函数名,state指向上述的state ...
  • axios跨域,及axios中this指向

    千次阅读 2018-08-03 18:33:26
    安装  npm install axios --save-dev ... 两种解决思路:一 修改原型链,二 axios+vuex 进行封装 一. main.js 引入 axios 并且修改原型链: import axios from 'axios' ​ Vue.prototype....
  • Vuex

    2020-07-12 19:55:48
    什么是Vuex ...vuex在项目的应用和项目的使用过程和搭建过程 第一步搭建项目: npm install vuex --save 第二步引用vuex: 在项目目录创建一个store的文件夹,在文件夹下创建index.js文件,文
  • vuex中mutations一个方法需要调用另外一个方法

    万次阅读 热门讨论 2018-12-13 10:17:12
    vuex中的mutations方法,想调用mutations的另外一方法,还是用commit,只需要使用this.commit('function'),当前的this指向的就是当前模块的mutations;
  • vuex

    2020-09-03 18:59:34
    vuex Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。...2.不能直接修改Vuex的状态:如果是个全局对象变量,要修改很容易,但是在Vuex中不能这样做,想修改就得使用Vuex提供的唯一途径:显示地提交
  • 在上一篇在中发现了electron-vuethis指向出现问题,在主进程和渲染进程之间通信的时候,尝试了不管使用何种方式,在ipRendererthis永远指向窗口即electron,而不是指向我们的Vue。 更正一个问题,昨天说到我在...
  • vuex的actions. js无法通过this. $router获取路由的问题,参考了以下解决方法 先把跟组件导出 然后在actions导入 就可以获取到了
  • vuex中mutation和action的详细区别

    万次阅读 2019-04-16 10:27:11
    被问到,死惨了,总结下 ...一、vuex中mutation和action的详细区别 const store = new Vuex.Store({ state: { count: 0 }, mutations: { increment (state) { state.count++ } }, actions: { increment...
  • Vuex安装阶段,store实例往每一个组件上混入beforeCreate钩子函数,添加一个指向它的 $store 实例。这样我们可以在组件通过 $store 访问store的任何属性和方法。 但是当一个组件需要获取多个状态时,将这些都声明...
  • vuex中的store.replaceState()

    千次阅读 2020-05-16 14:23:47
    在最近的学习,博主需要在vue-cli脚手架的项目同时使用vuex与iframe,并且需要在主页面改变vuex内相应的值之后在iframe内能够实时的看到对应的变化,话不多说上代码。 home.vue <template> <div ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 5,508
精华内容 2,203
关键字:

vuex中的this指向

vue 订阅