简体   繁体   中英

vue bind this to imported rule function

I have multi Vue files that share the same string validation check logic like:

data(){
        return {
            dialog: false,
            unitEditing:{},
            codeRules:[
                v => !!v || 'can't be empty',
                v => !(/\s/g.test(v)) || 'can't contain space'
            ],
            idRules:[
                v => !!v || 'can't be empty',
                v => !(/\s/g.test(v)) || 'can't contain space',
                v => (this.unitEditing.platform != "unity" || (v=="video" || v=="rewardedVideo")) || "placement for unity should only be video or rewardedVideo"
            ],
        }
    },

I think it would be nice that I make a utils file ( ../utils/miscUtils.js ) for this:

var MiscUtils = {
    rules: {
        codeRules:[
                v => !!v || 'can't be empty',
                v => !(/\s/g.test(v)) || 'can't contain space'
            ],
        idRules:[
                v => !!v || 'can't be empty',
                v => !(/\s/g.test(v)) || 'can't contain space',
                v => (this.unitEditing.platform != "unity" || (v=="video" || v=="rewardedVideo")) || "placement for unity should only be video or rewardedVideo"
            ],
    }
}

export default MiscUtils;

So that I could use:

import MiscUtils from '../utils/miscUtils'
...
data(){
        return {
                dialog: false,
                unitEditing:{},
                codeRules:MiscUtils.rules.codeRules,
                idRules:MiscUtils.rules.idRules
            }
        },

But the thing is that we are referring this.unitEditing in our check rules. I also tried

idRules:MiscUtils.rules.idRules.bind(this)

And it says that MiscUtils.rules.idRules is not a function so can not bind.

How can I achieve this?

idRules is an Array , but you're trying to call Function#bind on it ( Array has no bind method). But Function#bind wouldn't help because the arrow function's context is already bound and cannot be re-bound .

One solution is to make idRules a function that takes a component instance as the argument and returns an Array :

var MiscUtils = {
    rules: {
        codeRules: [
                v => !!v || 'can\'t be empty',
                v => !(/\s/g.test(v)) || 'can\'t contain space'
            ],
        idRules: comp => [
                v => !!v || 'can\'t be empty',
                v => !(/\s/g.test(v)) || 'can\'t contain space',
                v => (comp.unitEditing.platform != "unity" || (v=="video" || v=="rewardedVideo")) || "placement for unity should only be video or rewardedVideo"
            ],
    }
}

Then in your component:

data() {
  return {
    dialog: false,
    unitEditing: {},
    codeRules: MiscUtils.rules.codeRules,
    idRules: MiscUtils.rules.idRules(this)
  }
},

idRules is an array, not a function; to give the individual rules the context of this , you'll need to make this misc utils a factory function, so that you could do something like:

var MiscUtils = function () {
  return {
    rules: {
      codeRules: [
        v => !!v || "can't be empty",
        v => !(/\s/g.test(v)) || "can't contain space"
      ],
      idRules: [
        v => !!v || "can't be empty",
        v => !(/\s/g.test(v)) || "can't contain space",
        v => (this.unitEditing.platform != "unity" || (v == "video" || v == "rewardedVideo")) || "placement for unity should only be video or rewardedVideo"
      ]
    }
  }
}

And in the calling part:

{
  data() {
    return {
      dialog: false,
      unitEditing: {},
      // Spread the individual rules
      ...MiscUtils.call(this).rules
    }
  }
}

Or alternatively, pass the context as a parameter:

var MiscUtils = context => ({
  rules: {
    codeRules: [
      v => !!v || "can't be empty",
      v => !(/\s/g.test(v)) || "can't contain space"
    ],
    idRules: [
      v => !!v || "can't be empty",
      v => !(/\s/g.test(v)) || "can't contain space",
      v => (context.unitEditing.platform != "unity" || (v == "video" || v == "rewardedVideo")) || "placement for unity should only be video or rewardedVideo"
    ]
  }
})

Why not using mixins :

miscUtils.js:

export default {
    data() {
        return {
            codeRules: [v => !!v || "can't be empty", v => !/\s/g.test(v) || "can't contain space"],
            idRules: [
                v => !!v || "can't be empty",
                v => !/\s/g.test(v) || "can't contain space",
                v =>
                    this.unitEditing.platform != "unity" ||
                    v == "video" ||
                    v == "rewardedVideo" ||
                    "placement for unity should only be video or rewardedVideo"
            ]
        };
    }
};

and you can import this file in your vue component and set mixins:

import miscUtils from "FILE_PATH";
export default {
    mixins: [miscUtils],
    data() {
        return {
            dialog: false,
            unitEditing: {}
        };
    },
};

and now you can use your validation and this refer to component instance.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM