GithubHelp home page GithubHelp logo

vue-timers's Introduction

vue-timers

Simple mixin to manage timers or intervals for Vue.js

Installation

1.1 Use CDN

<script src="https://cdn.jsdelivr.net/npm/vue-timers/dist/vue-timers.umd.js"></script>

1.2 Install from package manager

npm install vue-timers
yarn add vue-timers

2.1. Global import

import Vue from 'vue'
import VueTimers from 'vue-timers'

Vue.use(VueTimers)

2.2. Or use mixin for the specific component

import {mixin as VueTimers} from 'vue-timers'

export default {
  mixins: [VueTimers]
}

2.3. Nuxt plugins

nuxt.config.js:

export default {
  plugins: [
    { src: '~/plugins/vue-timers', mode: 'client' }
  ]
}

plugins/vue-timers.js:

import Vue from 'vue'
import VueTimers from 'vue-timers'

Vue.use(VueTimers)

What it does?

It creates timer instances in components and slightly reduces boilerplate code with their handling.
See the following code

export default {
  methods: {
    log () {
      console.log('Hello world')
    }
  },
  created () {
    // It looks OK for the first look
    // But imagine that you have more than one timer
    this.$options.interval = setInterval(this.log, 1000)
    // Ok? What about check if timer works?
    // And it's not reactive so you should create data option
    console.log(this.$options.interval !== null)  
    // Still ok? So what about reusable timers?
    // New method for that? Rly?  
  },
  // Did you forget that it should be destroyed?
  beforeDestroy () {
    clearInterval(this.$options.interval)
  }
}

It's ugly, isn't it? So let's try to fix this :)

Same code with vue-timers:

export default {
  timers: {
    log: { time: 1000, autostart: true }
  },
  methods: {
    log () {
      console.log('Hello world')
    }
  }
}

Configuration

Timer object

{
  // Name of timer
  // Default: timer key (with object notation)
  name: String,

  // Tick callback or method name from component
  // Note: callback is binded to component instance
  // Default: name
  callback: Function/String,

  // Autostart timer from created hook
  // Default: false
  autostart: Boolean,

  // Set true to repeat (with setInterval) or false (setTimeout)
  // Default: false
  repeat: Boolean,

  // Set true to call first tick immediate 
  // Note: repeat must be true too
  // Default: false
  immediate: Boolean,

  // Time between ticks
  // Default: 1000
  time: Number
  
  // Switch timer`s status between activated and deactivated
  // Default: false
  isSwitchTab: Boolean
}

Changing timer duration

this.timers.log.time = 2000

NOTE: you should restart timer to apply changes

Component methods

// Starts `log` timer
this.$timer.start('log')
// Stops `log` timer
this.$timer.stop('log')

isRunning property

this.timers.log.isRunning

Events

TimerComponent.vue

import { timer } from 'vue-timers'

export default {
  timers: [
    timer('log', 1000)
  ],
  methods: {
    log () {
      console.log('It works!')
    }
  }
}

App.vue

<template>
  <timer-component
    @timer-start:log="timerStarted"
    @timer-stop:log="timerStopped"
    @timer-tick:log="timerTicked"
  />
</template>

3 ways of timers declaration

Object notation

export default {
  timers: {
    log: { time: 1000, ...options }
  }
}

Array notation

export default {
  timers: [
    { name: 'log', time: 1000, ...options }
  ]
}

Helper function

import { timer } from 'vue-timers'

export default {
  timers: [
    timer('log', 1000, { ...options })
  ]
}

Author

Anton Kosykh

License

MIT

vue-timers's People

Contributors

dependabot[bot] avatar gregpeden avatar jeremywohl avatar kalabasa avatar kelin2025 avatar masongzhi avatar mcpower avatar wegenern avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

vue-timers's Issues

Use factory function to allow access to vm

Hi, thanks for this mixin!
I've got one little issue with it:

it would be nice nice to be able to pass factory function to "timers" options object, which would have access to vue instance, so I can, for example, use data from props to set time property of timer.

Example:

timers: {
  visibilityTimer() {
    return {
      autostart: false,
      callback() {
        // ...
      },
      time: this.timeout, // <- I am not able to do this now.
    }
  },
},

What do you think? Should I do an PR?

cannot change .time property (typo?)

my usecase: I set a default value for 'time' but before starting the timer I want to change it (the value to use comes from an API)
however, due to a typo in mixin.js it will always use the default value.
my code:

    timers: {
      settings: {
        callback: ...,
        autostart: false,
        repeat: true,
        immediate: false,
        time: 60*1000,
      }
    },

then, in the component's created() I do something like:

            this.timers.settings.time = 5 * 1000;
            this.$timer.start('settings');

(instead of 5 I'm using a dynamic value)

as I see, the problem comes from a typo in mixin.js, line #97:

        data[name].instance = generateTimer(
          set('timer', data[name].time, options[name]),
          vm
        )

if I change it to

set('time', data[name].time, options[name]),

it works as expected.

Timer creates new instances when switching Tabs

"vue-timers": "2.0.4",
"vue": "2.6.11",
"bootstrap-vue": "2.15.0"

We have a Component (resultViewer) which loads Data with a timer, the timer is defined like this

  timers: {
    autoRefreshTimerCallback: { time: 5000, repeat: true, isSwitchTab: true, immediate: false }
  },

and is started / stopped in a vue-watch and in vue-deactivated, vue-activated

activated () {
  if (this.isAutoRefreshActive) {
    this.$timer.start('autoRefreshTimerCallback')
  }
},
deactivated () {
  this.$timer.stop('autoRefreshTimerCallback')
},
 watch: {
    isAutoRefreshActive: function (val) {
      if (val) {
        this.$timer.start('autoRefreshTimerCallback')
      } else {
        this.$timer.stop('autoRefreshTimerCallback')
      }
    }
}

This Component is used in several Pages and when we switch between those Pages with a running timer it creates a new timer instance.

Here is an example of a console log were we have a resultViever instance with ID 0 and one with ID 3.
We start on the page with resultViever ID 0, where the timer instance is 33. We then switch to the page with resultViever ID 3, where the timer instance is 231. We deactivate the timer on this page (ID 3) and go back on the first page . Now on the first page (ID 0) the timer instance is 334. Now going again on page 2 (ID 3) the timer instance is 418 and is active even though we deactivated it. This timer now goes on indefinitely.


resultsViewer/postRefreshGraph[0] active Options: Auto Refresh
resultsViewer/postRefreshGraph[0] active Options: Auto Refresh

Timer instance: 33 isRunning: true
resultsViewer/postRefreshGraph[0] active Options: Auto Refresh

resultsViewer/postRefreshGraph[3] active Options:

loading data:
spectrum:recent(10) jcbLog.js:135

resultsViewer/postRefreshGraph[3] active Options:

loading data:
spectrum:recent(10) jcbLog.js:135

resultsViewer/postRefreshGraph[3] active Options: Auto Refresh
Timer instance: 231 isRunning: true
resultsViewer/postRefreshGraph[3] active Options: Auto Refresh
resultsViewer/postRefreshGraph[3] active Options:

loading data:
spectrum:recent(10) jcbLog.js:135

resultsViewer/postRefreshGraph[0] active Options: Auto Refresh
Timer instance: 334 isRunning: true
resultsViewer/postRefreshGraph[0] active Options: Auto Refresh
Timer instance: 334 isRunning: true
resultsViewer/postRefreshGraph[0] active Options: Auto Refresh

resultsViewer/postRefreshGraph[3] active Options:
Timer instance: 418 isRunning: true

loading data:
spectrum:recent(10) jcbLog.js:135

Timer instance: 418 isRunning: true
resultsViewer/postRefreshGraph[3] active Options:

Don't work with component props

Hi,

Im trying set interval dynamically from props:

props: {
    interval: {
      type: Number,
      default: 10000
    }
},
timers: {
    getRemoteData: {
      time: this.interval,
      autostart: true,
      repeat: true,
      immediate: true
    }
},

But the timer is firing with interval infinite. If i change "this.interval" to "10000" it work normally.

Can anyone help me?

Thanks.

Combine Timer with Mouse Idle

It would be a good addition to the timer to allow for checking if mouse has been idle for a specific amount of time before the timer starts.

Dynamic Timers

I am trying to create a number of dynamic timers in the mounted lifecycle event of a component:

  mounted() {
    if (this.jobs) {
      for (let job of this.jobs) {
        this.$store.dispatch(`dashboard-${this.id}/LOAD_DATA`, { elementId: job.name, service: job.service })
        if (job.refresh && job.refresh.interval) {
          this.timers[`${this.id}-${job.name}`] = {
            name: `${this.id}-${job.name}`,
            time: job.refresh.interval,
            autostart: false,
            repeat: true,
            callback() {
              this.$store.dispatch(`dashboard-${this.id}/LOAD_DATA`, { elementId: job.name, service: job.service })
            }
          }
          console.log(this.timers)
          this.$timer.start(`${this.id}-${job.name}`)
        } else {
          this.$timer.stop(`${this.id}-${job.name}`)
        }
      }
    }
  },

But, when it gets to the $timer.start() call, I get the following: "[vue-timers.start] Cannot find timer tal-cs-tier1-callsInbound". The console.log(this.timers)shows that the timer object exists. I have tired both object notation and array.

Error in data(): "ReferenceError: process is not defined"

while trying to run inside https://jsfiddle.net/:

plugin assumes node.js context is present:
https://github.com/Kelin2025/vue-timers/blob/master/mixin.js#L32

vue.js:634 [Vue warn]: Error in data(): "ReferenceError: process is not defined"

(found in <Root>)
vue.js:1897 ReferenceError: process is not defined
    at normalizeConfig (mixin.js:33)
    at mixin.js:69
    at Array.reduce (<anonymous>)
    at normalizeOptions (mixin.js:66)
    at Vue.data (mixin.js:78)
    at Vue.mergedInstanceDataFn (vue.js:1240)
    at Vue.mergedInstanceDataFn (vue.js:1243)
    at getData (vue.js:4739)
    at initData (vue.js:4696)
    at initState (vue.js:4635)
vue.js:634 [Vue warn]: Error in mounted hook: "ReferenceError: process is not defined"

(found in <Root>)
vue.js:1897 ReferenceError: process is not defined
    at Object.start (mixin.js:91)
    at mixin.js:140
    at Array.forEach (<anonymous>)
    at Vue.mounted (mixin.js:138)
    at invokeWithErrorHandling (vue.js:1863)
    at callHook (vue.js:4214)
    at mountComponent (vue.js:4081)
    at Vue.$mount (vue.js:9038)
    at Vue.$mount (vue.js:11923)
    at Vue._init (vue.js:5006)

Jest SyntaxError: Unexpected token export

I know an issue isn't the best place for this, but I thought it should be documented somewhere.

Vue-timers was working as a global import or mixin in my app. However, it completely broke all my Jest tests. The errors thrown varied from TypeError: Cannot read property 'setData' of undefined to SyntaxError: Unexpected token export depending on what I tried to fix it.

I finally realized that I needed to update my jest.config.js from:

  transformIgnorePatterns: [
    'node_modules/',
  ],

to

  transformIgnorePatterns: [
    'node_modules/?!(vue-timers)',
  ],

This is probably obvious for someone with more Jest experience, but I figured I should document what I found since it took me way too long to track down.

TS7016: Could not find a declaration file for module 'vue-timers'

I am trying to use the Vue plugin in my application on a component withlang="ts"set up. Another component uses this plugin just fine, but that component is not using typescript.

When I compile, I get the following error:

  [tsl] ERROR in /src/renderer/components/ApplicationStatus.vue.ts(8,36)
        TS7016: Could not find a declaration file for module 'vue-timers'. '/node_modules/vue-timers/index.min.js' implicitly has an 'any' type.

I've tried creating a shim.d.ts file with the line

declare module 'vue-timers';
But that didn't really help. Not sure how to proceed on this.

ERROR in build.js from UglifyJs Unexpected token: punc (,)

I'm getting this error when I run npm run build

ERROR in build.js from UglifyJs
Unexpected token: punc (,) [./node_modules/vue-timers/index.js:8,24][build.js:93235,29]

If I take out the vue-timers from main.js and my components, then it compiles fine. Any idea how to fix this?

My webpack config is

var path = require('path')
var webpack = require('webpack')
const ExtractTextPlugin = require("extract-text-webpack-plugin")

module.exports = {
  entry: './src/main.js',
  output: {
    path: path.resolve(__dirname, './dist'),
    publicPath: '/dist/',
    filename: 'build.js'
  },
  module: {
    rules: [
      {
        test: /\.vue$/,
        loader: 'vue-loader',
        options: {
          loaders: {
          },
          // other vue-loader options go here
          transformToRequire: {
            'img': 'src',
            'image': 'xlink:href',
            'b-img': 'src',
            'b-img-lazy': ['src', 'blank-src'],
            'b-card': 'img-src',
            'b-card-img': 'img-src',
            'b-carousel-slide': 'img-src',
            'b-embed': 'src'
          }
        }
      },
      {
        test: /\.js$/,
        loader: 'babel-loader',
        exclude: /node_modules(?![\\/]vue-awesome[\\/])/
      },
      {
        test: /\.css$/,
        use: ExtractTextPlugin.extract({
          fallback: "style-loader",
          use: "css-loader"
        })
      },
      {
        test: /\.(png|jpg|gif|svg)$/,
        loader: 'file-loader',
        options: {
          name: '[name].[ext]?[hash]'
        }
      }
    ]
  },
  resolve: {
    alias: {
      'vue$': 'vue/dist/vue.esm.js'
    },
    extensions: ['*', '.js', '.vue', '.json']
  },
  devServer: {
    historyApiFallback: true,
    noInfo: true
  },
  performance: {
    hints: false
  },
  plugins: [new ExtractTextPlugin("main.css")],
  devtool: '#eval-source-map'
}

if (process.env.NODE_ENV === 'production') {
  module.exports.devtool = '#source-map'
  // http://vue-loader.vuejs.org/en/workflow/production.html
  module.exports.plugins = (module.exports.plugins || []).concat([
    new webpack.DefinePlugin({
      'process.env': {
        NODE_ENV: '"production"'
      }
    }),
    new webpack.optimize.UglifyJsPlugin({
      sourceMap: true,
      compress: {
        warnings: false
      }
    }),
    new webpack.LoaderOptionsPlugin({
      minimize: true
    })
  ])
}
else {
  module.exports.plugins = (module.exports.plugins || []).concat([
    new webpack.DefinePlugin({
      'process.env': {
        NODE_ENV: '"development"'
      }
    }),
  ])
}

Feature Request: pause/start timer when the page visibility changes

The Page Visibility API is especially useful for saving resources and improving performance by letting a page avoid performing unnecessary tasks when the document isn't visible.

https://developer.mozilla.org/en-US/docs/Web/API/Page_Visibility_API

One of the unnecessary tasks which in many apps could be avoided is running a timer when the page isn't even visible.

I'm willing to send a pull request later if you are interested in having this in the library.

Fix tests

After updating babel, tests fail with the weird error image
According to babel docs, targets option is valid
image

🤔

Attempts to remove $timer's methods

This errors clutters the screen on route change: Error in beforeDestroy hook: "TypeError: timers[name] is undefined"

And this is due to this:

vue-timers/mixin.js

Lines 140 to 142 in dfb19a4

for (var name in this.$timers) {
this.$timers.remove(name)
}

this.$timers contains some methods such as add and it fails when iterating through those, because they aren't actual timers.

reactivity

Hi,

For some reason, I cant get the data reactive.
It's updating, but it isn't reactive.

export default {
        mixins: [VueTimers],
        timers: {
            setItems: { time: 1000, autostart: true, repeat: true }
        },
        data() {
            return {
                cycle: 1,
            }
        },
        methods: {
            setItems(){
                this.cycle++;
            }
        }

    }

browser support

  1. to work in bare browser (no import, no webpack) most vue plugins provide umd dist, i.e.:
    https://github.com/vuejs/vue-router/blob/dev/dist/vue-router.js
    https://github.com/LinusBorg/portal-vue/blob/develop/dist/portal-vue.umd.js

  2. in order for browser import to work
    https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import

these:
https://github.com/Kelin2025/vue-timers/blob/master/index.js

import VueTimers from './mixin'

should use *.js

import VueTimers from './mixin.js'

TypeScript Setup documentation needed

I have created a simple timer component in using typescript, but the timer isn't started. Any idea what I'm doing wrong?

<script lang="ts">
import { Component, Vue, Prop } from 'vue-property-decorator';
import { mixin as VueTimers } from 'vue-timers';

@Component({ mixins: [VueTimers] })
export default class ApplicationStatus extends Vue {
  private time: string = new Date().toString();

  timers: {
    tick: { time: 2000; autostart: true; repeat: true };
  };

  tick() {
    this.time = new Date().toString();
    console.debug(new Date());
  }
}
</script>

Feature Request: Stop timers based on inViewport

Nice work on the automagically removing the timers on beforeDestroy. Another performance win would be to check whether the component is in viewport or not and then disable/enable the timers.

Any thoughts on this? Would love to do a PR :)

Dont work with NUXT.

Dear creators of Vue-timers! I am a simple hard worker from Russia. I type this message through a Google translator.
I really need your library in my small project. But it does not work under NUXT. As soon as I try to import a vue-timers, the application stops compiling with an error like this:
SyntaxError
Unexpected token export
Please help me figure out how to integrate your library into the NIKST.

TypeError in utils.js as of 1.4+

After update from 1.3 to 1.4+ i'm getting errors in that code:

const clone = this.assign({}, obj)

TypeError: Cannot read property 'assign' of undefined at set (utils.js?0032:5)

I'm importing timers as a mixin. Using Nodejs8.11 and Chromium 65.

I wasn't able to find a solution or workaround other than rollback
And reverting to 1.3 solved the problem.

How to pass params to method?

Hi, how to pass some params to my method?
Something like this:

timers: {
foo: {time: 1000, params: {msg: 'my msg!'}}
},
methods: {
foo(msg = null) {
if (msg) console.log(msg)
else console.log('default msg')
}
}

UglifyJS throws Unexpected token: keyword (const) in build

The full error is:

ERROR in js/app.44949af3ee23bd7.js from UglifyJs
Unexpected token: keyword (const) [./node_modules/vue-timers/utils.js:1,7][js/app.44949af3ee23bd7.js:60908,0]

From what I read it happens because node_modules is ignored by default when building using webpack and babel. I'm not sure if that means that you need to transpile the code before uploading it. I'm still searching but I haven't found a solution yet that allows me to transpile a specific module, my only option is to manually edit the code of vue-timers, which breaks everytime I recreate node_modules.

Check this answer I found for context https://stackoverflow.com/questions/51289261/babel-does-not-transpile-imported-modules-from-node-modules

reuse timer to reduce waste of resource

Use a global timer pool to manage the "timers" and events.

Create a real timer and many virtual timers.

When a new timer coming, we need recalc the proper internal value and maybe free the old real timer and create the new one.

How do I get/set the timers globally?

Is there some way built in, or do I need to create my own "link"?
I have a component that does multiple timers and want another component to serve as a "control panel" to set time, start/stop.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.