fabriziocaldarelli/yii2-vueapp

一个用于在Yii2中创建Vue应用的帮助程序,无需webpack或类似工具

安装: 434

依赖: 0

建议者: 0

安全: 0

星标: 52

关注者: 7

分支: 4

开放问题: 0

类型:yii2-extension

1.0.1 2020-05-28 08:04 UTC

This package is auto-updated.

Last update: 2024-09-28 20:09:22 UTC


README

Latest Stable Version Total Downloads Build Status

这是一个组件,它帮助创建Vue.js应用,而无需使用webpack或类似工具。

所有资源(js、css和模板)都直接注入到html中,并且这个组件提供了分割代码(js、css和模板)以及从html根元素加载参数的功能。

此组件嵌入两个默认包:Axios和Moment。有一个示例演示了如何在代码中使用这两个包。

安装

通过 composer 安装此扩展是首选方式。

运行以下命令:

php composer.phar require --prefer-dist fabriziocaldarelli/yii2-vueapp "^1.0"

或者将以下内容添加到您的 composer.json 文件的require部分:

"fabriziocaldarelli/yii2-vueapp": "^1.0"

工作原理

此组件将js、css和tpl(php或html)文件注入到返回的html中。

这些文件从操作视图文件相同的文件夹开始读取,添加vueapp/actionName/js或vueapp/actionName/css或vueapp/actionName/tpl。

VueApp::begin主要支持三个参数:

  • id:vue应用html标签id选择器;
  • propsData:小部件使用此元素将数据从html/php传递到js脚本;
  • packages:应该加载到js vue脚本中的包列表

注意propsData 键在php和js文件中具有相同的名称(和相同的字母大小写)。

用法

1) 视图文件

在视图内部调用VueApp小部件

<?php
use \sfmobile\vueapp\VueApp;

/*
- Css files are automatically loaded from vueapp/test/css/
- Template files are automatically loaded from vueapp/test/tpl/
- Js files are automatically loaded from vueapp/test/css/
- Passing packages parameter we require Axios and Moment package

To pass data from php/html to js vue app we defined propsApp attribute data in VueApp configuration and the we fill in html converting from camel case to dash
*/

VueApp::begin([
    'id' => 'vueAppTest',
    'propsData' => [
        'kParam1' => 'value_1',
        'kParam2' => 'value_2',
        'kParam3' => 'value_3',
        'kParamObj' => ['a' => 10],
    ],
    /*
    'jsFiles' => [ ... ],    // list of other js files, that have precedente over js contents path files
    'cssFiles' => [ ... ],    // list of other css files, that have precedente over css contents path files
    'tplFiles' => [ ... ],    // list of other tpl files, that have precedente over tpl contents path files
    */
    'assets' => [ 
      \sfmobile\vueapp\assets\axios\AxiosAsset::class, 
      \sfmobile\vueapp\assets\moment\MomentAsset::class, 
      \sfmobile\vueapp\assets\vue_select\VueSelectAsset::class 
      \sfmobile\vueapp\assets\uid\UivAsset::class 
      \sfmobile\vueapp\assets\vue_bootstrap_datetime_picker\VueBootstrapDatetimePickerAsset::class 
    ]    
]);
?>
    kParam1: {{ propsApp.kParam1 }}
    <br />
    kParam2: {{ propsApp.kParam2 }}
    <br />
    kParam3: {{ propsApp.kParam3 }}
    <br />
    kParamObj: {{ propsApp.kParamObj ? propsApp.kParamObj.a : null }}
    <br />
    <!-- Refer to https://github.com/charliekassel/vuejs-datepicker -->
    <vuejs-datepicker></vuejs-datepicker>
    <br />
    clock datetime: {{ clock_datetime | formatDateTime('DD/MM/YYYY HH:mm') }}
    <br />
    <date-picker name="date" v-model="datePickerValue" :config="vueBootstrapDatetimePickerOptions"></date-picker>


<?php VueApp::end(); 

最重要的参数是packages,它加载嵌入的包,如Axios和Moment。

您必须安装在assets属性中声明的所有包

$ php composer.phar require --prefer-dist fabriziocaldarelli/yii2-vueapp-uiv "^1.0"
$ php composer.phar require --prefer-dist fabriziocaldarelli/yii2-vueapp-vue-select "^1.0"
$ php composer.phar require --prefer-dist fabriziocaldarelli/yii2-vueapp-vuejs-datepicker "^1.0"
$ php composer.phar require --prefer-dist fabriziocaldarelli/yii2-vueapp-vue-bootstrap-datetime-picker "^1.0"
$ php composer.phar require --prefer-dist fabriziocaldarelli/yii2-vueapp-moment "^1.0"
$ php composer.phar require --prefer-dist fabriziocaldarelli/yii2-vueapp-axios "^1.0"

2) Vue应用js文件

从视图路径文件夹开始,应用和组件的js文件位于vueapp/test/js/actionName/ .。

例如,主vue应用js的路径可能是vueapp/test/js/test.js

// Uix package asset - To avoid conflits:
// Vue.use(uiv, {prefix: 'uiv'}) : Components such as <alert> becomes <uiv-alert>

// Vue Select asset - To avoid conflicts:
// Vue.component('v-select', VueSelect.VueSelect);

var ___VUEAPP_APP_ID___ = new Vue({
    el: '#___VUEAPP_APP_ID___',

    // If you need a date picker,
    // add VueApp::PKG_VUEJS_DATEPICKER to 'packages' VueApp widget config
    // Refer to https://github.com/charliekassel/vuejs-datepicker
    components: {
        vuejsDatepicker,                                 // using VueJsDatePicker
        "date-picker": VueBootstrapDatetimePicker,       // using VueBootstrapDatetimePicker - https://github.com/ankurk91/vue-bootstrap-datetimepicker
        'v-select' : VueSelect.VueSelect                             // using VueSelect - https://vue-select.org/guide/install.html#yarn-npm
    },

    data: {

        /**
         * propsApp is used to collect attribute related to root container element.
         * This is the suggested way to pass data from php to js vue app.
         * All parameter are converted from dash to camel case (html k-param-1 become kParam1)
         */
        propsApp: {
            kParam1: null,
            kParam2: null,
            kParam3: null,
            kParamObj: null,
        },

        clock_datetime: null,

        datePickerValue: null,

        vueBootstrapDatetimePickerOptions: {
            // https://moment.js.cn/docs/#/displaying/
            format: "DD/MM/YYYY HH:mm",
            locale: 'it',
            useCurrent: false,
            showClear: true,
            showClose: true
        }        
    },

    filters: {
        formatDateTime: function (value, format) {
            return value ? moment(value).format(format) : null
        }
    },

    mounted() {
        this.readPropsApp();

        // Because kParamObj is an object, we have to parse to serialized version of kParamObj
        this.propsApp.kParamObj = JSON.parse(this.propsApp.kParamObj);

        this.loadAtomicClock();
    },

    methods: {

        readPropsApp: function () {
            for (var k in this.propsApp) {

                // Taken from: https://github.com/sindresorhus/decamelize/blob/master/index.js
                var attr = k
                .replace(/([a-z\d])([A-Z])/g, '$1-$2')
                .replace(/([A-Z]+)([A-Z][a-z\d]+)/g, '$1-$2')
                .toLowerCase();

                console.log(k, attr);
                if (this.$el.attributes[attr] != undefined) {
                    this.propsApp[k] = this.$el.attributes[attr].value;
                }
            }
        }

        loadAtomicClock: function () {

            var self = this;

            axios
                .get('http://worldtimeapi.org/api/ip')
                .then(function (response) {
                    console.log(response);
                    self.clock_datetime = response.data.datetime;
                })
                .catch(error => console.log(error));
        },

    }
})

3) Vue应用css文件

从视图路径文件夹开始,应用和组件的css文件位于vueapp/test/css/actionName/ .。

例如,主vue应用css的路径可能是vueapp/test/css/test.css

[v-cloak] {
    display: none
}

技巧与窍门

1. 将数据从html/php传递到js

要将数据从html/php传递到js vue应用,我使用了名为propsApp的属性,在其中定义了传递到html根元素的属性。

例如,html根元素 "vueAppTest"

<div id="vueAppTest" v-cloak
    k-param-1="value_1"
    k-param-2="value_2"
    k-param-3="value_3"
>
...
</div>

当应用挂载时(调用readPropsApp方法),会读取data.propsApp中定义的所有参数

var vueAppTest = new Vue({
    el: '#vueAppTest',
    data: {

        /**
         * propsApp is used to collect attribute related to root container element.
         * This is the suggested way to pass data from php to js vue app.
         * All parameter are converted from dash to camel case (html k-param-1 become kParam1)
         */
        propsApp: {
            kParam1: null,
            kParam2: null,
            kParam3: null,
        },

    },

    mounted() {
        this.readPropsApp();
    },

    methods: {

        readPropsApp: function () {
            for (var k in this.propsApp) {

                // Taken from: https://github.com/sindresorhus/decamelize/blob/master/index.js
                var attr = k
                .replace(/([a-z\d])([A-Z])/g, '$1-$2')
                .replace(/([A-Z]+)([A-Z][a-z\d]+)/g, '$1-$2')
                .toLowerCase();

                console.log(k, attr);
                if (this.$el.attributes[attr] != undefined) {
                    this.propsApp[k] = this.$el.attributes[attr].value;
                }
            }
        },
    }
}

2. 组件注册

当应用js文件依赖于其他js文件时,js文件加载顺序很重要。

因此,我建议所有组件文件使用'_'前缀或使用'.component.'后缀,以便首先加载组件js文件。

3. 将对象数据从html/php传递到js

将对象/数组从html/php传递到js的方式与原始数据类型相同(提示和技巧#1)。

唯一的区别是在mounted()函数中需要将json字符串解析为对象。

因此,如果kObject是从php传递的对象,mounted()方法将是

mounted() {
    this.readPropsApp();

    // Because kParamObj is an object, we have to parse to serialized version of kParamObj
    this.propsApp.kParamObj = JSON.parse(this.propsApp.kParamObj);
},