Views: 2660
Last Modified: 28.04.2022

  Connecting Pinia and creating a storage

Connect the extension ui.vue3.pinia inside your own extension or at php page to start the operation.

Import createPinia from ui.vue3.pinia in your extension for Pinia storage to work in your extension:

import {createPinia} from 'ui.vue3.pinia';
import {BitrixVue} from 'ui.vue3';

const store = createPinia();

const application = BitrixVue.createApp({
	components: {
		Component
	},
	template: '<Component/>'
});
application.use(store);
application.mount('#application'); 

Use the namespace BX.Vue3.Pinia within a page and scripts without transpiling and or feature access (for example, for createPinia, its BX.Vue3.Pinia.createPinia).

How to create a storage (module)

import {defineStore} from 'ui.vue3.pinia';

const exampleStore = defineStore('example', {
    ...
});

  State export (state/getters)

You need to use data storage in component template for this component to declare such values in template via calculated properties.

You can avoid writing all structure elements manually: use the helper function mapState (this function can be imported from ui.vue3.pinia):

computed: {
    ...mapState(counterStore, ['counter', 'double']),
},

The function allows importing variables in a free format:

computed: {
    ...mapState(counterStore, {
        myOwnName: 'counter',
        // you also write function that gets access to storage
        triple: store => store.counter * 3,
    }),
},

Or you can query the variable in a usual format:

computed: {
    counterStore: () => counterStore().counter,
},

  Action (actions) export

The same approach is applicable to methods: you need to export functions inside the component using the function mapActions (function can be imported from ui.vue3.pinia):

methods: {
    ...mapActions(counterStore, ['increaseCounter', 'decreaseCounter']),
	// as in the previous approach with mapState, you can rename parameters
    ...mapActions(useCounterStore, { decrease: 'decreaseCounter' }),
},

  Example

Now lets unify these two actions and launch the application.

Let's overview the action: place element with identifier application at your html-page:

<div id="application"></div>

Execute the following code in JS extension for associating html, Vue and Vuex (it creates a storage, registers component to handle the extension and launches Vue application):

import { BitrixVue } from 'ui.vue3';
import { createPinia, defineStore, mapState, mapActions } from 'ui.vue3.pinia';

// initialize Pinia
const store = createPinia();

// create a Counter storage: please note, its a unique name for all of page!
const counterStore = defineStore('counter', {
	state: () => ({
		counter: 0,
		changes: 0
	}),
	getters: {
		double()
		{
			return this.counter * 2;
		},
	},
	actions: {
        increaseCounter()
        {
            this.counter++;
        },
        decreaseCounter()
        {
            this.counter--;
        }
    },
});

// Create a component to work with a state from Pinia

const Component = {
	computed: {
        counterMessage()
        {
            return 'Counter: ' + this.counter;
        },
        doubleCounterMessage()
        {
            return 'Double counter:' + this.double;
        },
        ...mapState(counterStore, ['counter', 'double']),
    },
	methods: {
        ...mapActions(counterStore, ['increaseCounter', 'decreaseCounter']),
    },
	// language=Vue
	template: `
        <div>{{counterMessage}}</div>
        <div>{{doubleCounterMessage}}</div>
        <div>
            <button @click="increaseCounter">+</button>
            <button @click="decreaseCounter">-</button>
        </div>
    `
};

// Create an application, connect Pinia and render into the "#application" tag
const Application = BitrixVue.createApp({
	components: {
		Component
	},
	template: `
        <Component/>
    `
});
Application.use(store);
Application.mount('#application');

Important! Upon declaring storages, you need to very carefully choose names inside function defineStore – first parameter must be unique. This can cause issues, when you use the same storage for different Vue applications (for example, when two different widgets that must have identical storage structure, but with different data).





Courses developed by Bitrix24