Design Patterns (1): Perform only one function

Outline

Recent recently doing the project will always think of some big application design patterns related issues, I think his own record for future reference when developing, we believe it is useful to others.

Function is executed only once

We often encounter this situation, is the hope that a function is executed only once, after not performed . Under normal circumstances, we would write:

<script>
export default {
  data() {
    return {
      runOnce: true,
    };
  },
  methods: {
    func() {
      console.log('hello world', this);
    },
    funcRunOnce() {
      if (this.runOnce) {
        this.func();
        this.runOnce = false;
      }
    },
  },
};
</script>

But this is not elegant, not only pollute the data, also achieved by two methods, it is ugly.

Improvement closure

So we consider the use of closures , the data inside runOnce this variable into the closure inside, so it will not contaminate the data. code show as below:

<script>
export default {
  methods: {
    func() {
      console.log('hello world', this);
    },
    funcRunOnce(params) {
      let runOnce = true;
      return () => {
        if (runOnce) {
          this.func();
          runOnce = false;
        }
      }();
    },
  },
};
</script>

But it is written so clearly wrong, because every time funcRunOnce structure will be called once the closure, inside runOnce this variable will not be shared. So continue to read as follows:

// 方法1
<script>
export default {
  created() {
    this.funcRunOnce = this.runOnce(this.func);
  },
  methods: {
    func() {
      console.log('hello world', this);
    },
    runOnce(func) {
      let runOnce = true;
      return (params) => {
        if (runOnce) {
          func(params);
          runOnce = false;
        }
      };
    },
  },
};
</script>

// 方法2
<script>
export default {
  methods: {
    func() {
      console.log('hello world', this);
    },
    runOnce(func) {
      let runOnce = true;
      return (params) => {
        if (runOnce) {
          func(params);
          runOnce = false;
        }
      };
    },
    funcRunOnce: this.runOnce(this.func),
  },
};
</script>

Use utils

We can see, the above method is still very elegant, and created or implemented in a two ways, either by three methods. And all with a common approach runOnce. Therefore, we consider runOnce into utils.js go inside.

// utils.js
export function runOnce(func) {
  let runOnce = true;
  return (params) => {
    if (runOnce) {
      func(params);
      runOnce = false;
    }
  };
}

//example.vue
import { runOnce } from '@/utils';
<script>
export default {
  methods: {
    funcRunOnce: runOnce(() => {
      console.log('hello world', this);
    }),
  },
};
</script>

The above wording seems very simple, but in fact is not enough, because this point was wrong. Since the method does not function vue example runOnce returned, so this points to the inside of the undefined .

Note: Even if we look as if funcRunOnce method by an arrow function to capture this instance the outside, but in fact it captures this instance is not outside, but inside runOnce return of function of this.

Capture this

Where we can use the arrow functions are used, but why we still can not capture this it? It is not this way can not complete this task?

Not, or some method, the method is not a function of the arrow capture the this . code show as below:

// utils.js
export function runOnce(func) {
  let runOnce = true;
  return function(params) {
    if (runOnce) {
      func.apply(this, params);
      runOnce = false;
    }
  };
}

//example.vue
import { runOnce } from '@/utils';
<script>
export default {
  methods: {
    funcRunOnce: runOnce(function h() {
      console.log('hello world', this);
    }),
  },
};
</script>

As can be seen by looking at the code, where the two functions are rewritten become arrow function, and also uses the function to apply force is applied to this.

The reason is simple, because the runOnce function which does not use the arrow functions, the function which returns a part of vue instance, so this function it returns, pointing vue instance; and because funcRunOnce there is no use arrow function, so we can use apply to this func attached to this forced to go inside!

Similarly we can also write for the first time does not perform the function it performed follow-up:

// utils.js
// 第一次不执行,后续再执行
export function notRunOnce(func) {
  let once = false;
  return function(params) {
    if (once) {
      func.apply(this, params);
    }
    once = true;
  };
}

Learned what

  1. In vue initialization method which can be used in the form of assignment, or created inside the initialization method.
  2. Although the arrow function can capture this, but not everything; sometimes we need a function to capture and apply this combination.

Guess you like

Origin www.cnblogs.com/yangzhou33/p/11204180.html