A Vue component for JsPsych.
Compatible with most official plugins and extensions.
Feel free to use any third-party component in JsPsych! 🎉🎉🎉
Use yarn
yarn add jspsych-vue
Use npm
npm install jspsych-vue
Note: To use jspsych-vue, you should also add jspsych(v7) to your project, both npm install and CDN are supported. For more details, see https://www.jspsych.org/latest/tutorials/hello-world/
CDN are recommond.
Add css files to your project, which is look like:
import './assets/main.css'
import 'jspsych-vue/dist/style.css'
import 'jspsych/css/jspsych.css' // if use CDN, do not add this line.
import { createApp } from 'vue'
import App from './App.vue'
createApp(App).mount('#app')
Then in your component, you should pass options to init jspsych object. For npm user, you should also pass module props.
<script lang="ts" setup>
import * as jsPsychModule from 'jspsych' // for npm user
const options = {...} // any options
</script>
<template>
<JsPsych :options="options"></JsPsych>
<!-- for npm user, use module props -->
<JsPsych :options="options" :module="jsPsychModule"></JsPsych>
</template>
That's all!
Jspsych Plugin is the basic part of an experiement, it defines the interface, collects data, push the timeline and so on. By the way, there are plenty of plugins you can find in jspsych and jspsych-contrib.
Though Jspsych Plugin is powerful, the limitation is that you can only use js to draw the interface. So here comes Jspsych-Vue, which allows you to replace any Plugin by a Vue Component, and feel free to use any third-part UI component!
If you want to use a Component in JsPsych, make sure it meets following two requets:
- Export the
info
property at the top level of the component (see jsPsych Plugin) - Call
jsPschy.finishTrial
at the appropriate time to go to next trial.
Example:
<template>
<div>Anything you want to show...</div>
</template>
<script>
export default {
info: {
parameters: {...} // info just the same as Jspsych Plugin
},
setup(props) {
// no more trial function, just do anthing within setup.
...
jsPsych.finiTrial() // remember to finish trial at some point, like when user click the button.
}
}
</script>
For users of the setup sugar, you should define info like this.
<script setup>
const info = defineOptions({
parameters: {...}
})
</script>
Ensure not to use any local variables within
info
.
Same as the Plugin’s trial method, the Vue component can accepts two props:
trial
: Parameters from the parameters object that can be passed in when defining the timeline.on_load
: Callback function for the load event.
Please refer to the JsPsych documentation for details.
Just like psych, you should define the timelime to run trials. Create a JS file, for instance, timeline/xxx.js
in the root directory, then define a timeline. But insead of set a Jspsych Plugin to trial.type
, you should set a Vue Component to trial.component
.
Example:
//timeline/HelloWorld.ts
import HelloWorld from '@/component/HelloWorld.vue'
const timeline = [{ component: HelloWorld }]
export default timeline
If you need use a jsPsych instance to define the timeline, just export a function.
Example:
//timeline/HelloWorld.ts
import HelloWorld from '@/component/HelloWorld.vue'
const getTimeline (jsPsych: JsPsych) = [
{
component: HelloWorld,
on_finish: () => {
//You can use the jsPsych instance somewhere.
}
}
]
export default getTimeline
Simply put, you can replace the type of trial by component.
Define where to render the component and call run to start the experiment at a specific time.
Example:
<template>
<JsPsych @init="e => jsPsch = e"></JsPsych>
</template>
<script>
import timeline1 from '@/timeline/HellowWorld.ts'
var jsPsch = null
onMounted(() => {
jsPsch.run(timeline1)
})
</script>
That is the complete process for developing a Vue compont with jsPsych. Below are some details.
You can not use a component in a plugin(Because the trial itself define how to draw the dom, and it may overwrite the component), but you can still use Jspsych Plugin in Jspych-Vue.
Just use the origin way to define a trial, then push it in timeline. You can also define nested timelineNode use both component and trial. For more info see Nested timeline.
Here are the differences.
-
define trials:
plugin
let trial = { type: MyPlugin, parameters1: xxx, parameters2: xxx }
component
let trial = { component: MyComponent, props1: xxx, props2: xxxx }
-
use parameters and do trial:
plugin
class Plugin { trial(display_element, trial, on_load) { // draw something use js // do trial here } }
component
export default { setup(props) { let trial = props.trial // {props1: xxx, props2: xxx} let on_load = props.on_load //do trial here } }
-
run experiment
plugin / component
jsPsych.run([trial])
-
display data
plugin:
jsPsych.data.displayData('json')
component
jsPsych.data.displayData({ dom: el, type: 'json' })
When trial called, your component will be render as a child of Jspsych Component.
Every JsPsych component create a JsPsych instance. There are two methods to access it.
-
Use
init
event outside of a JsPsych component.Example:
<template> <JsPsych @init="init"></JsPsych> </template> <script setup> let jsPsych; const init = (instance: any) => jsPsych = instance; </script>
-
Using
provide
within a JsPsych component.Example:
<script setup> import { porvice } from 'vue' const jsPsych = provide('jsPsych') </script>
Jspsych-Vue component offer slots that allow you to show component before experiment start/after experiment end.
Example:
<JsPsych>
<div>Please wait...</div>
</JsPsych>
You can pass any componnet in timeline, then use it. Be careful to use a function return the component.
Example:
const timeline = [{ component: MyComponent, compSlot: () => MySlot }]
Then use it in your component:
<script setup>
const props = defineProps(['trial'])
const MySlot = props.trial.compSlot
</script>
<template>
<div>
....
<MySlot></MySlot>
<div>
</template>
Thats all about how to start.