The introduction
In today’s trend of front and rear end separation, there are still some requirements for front and rear end separation. Since the boss considered that webpack packaging was troublesome and time-consuming, which caused some problems in operation and maintenance, but he could not abandon the excellent functions such as Vue data binding, so the task of writing the project with yII + Vue + Element technology stack came into being without separation of the front and back ends, and THIS task was given to me.
The specific requirements
- Can encapsulate various components and call in PHP
- Some degree of customization is possible
- Try to write in PHP
Brain dust storm
- For the first problem, I chose to write with custom widgets in YII, which reuse view code in an object-oriented manner and meet configurable requirements.
- The second problem is that the widget can either pass several parameters for configuration or write a complete function to override it. (Ten faces mengbi)
- For the third question, that means putting as much code in the Controller as possible and assigning it to the widget.
The first edition
The first release addressed basic issues such as widget directory structure, the introduction of VUE, and how to mix PHP and JS.
-
Refers to the directory structure of the widget
Project ├ ── trash ├ ─ class.php Vue └ ─ ─ ─ components | └ ─ ─ ─ the Form │ │ FormView. PHP/parts/view file │ │ FormWidget. PHP │ └ ─ ─ ─ web └ ─ ─ ─ js └ ─ ─ ─ conponents └ ─ ─ ─ Form. Js // instantiate vueCopy the code
-
Specific code
AppAsset.php
<? php namespace app\assets; use yii\web\AssetBundle; class AppAsset extends AssetBundle { public$basePath = '@webroot'; public $baseUrl = '@web'; public $css = [ 'css/site.css'.'css/element-ui/index.css',]; public$js = [ 'js/vue/vue.js'.'js/element-ui/index.js',]; public$depends = [ 'yii\web\YiiAsset'.'yii\bootstrap\BootstrapAsset',]; }Copy the code
FormView.php
<? php use app\components\form\FormAsset; FormAsset::register($this); $this->registerJsFile('@web/js/components/form.js'['position'=> \yii\web\View::POS_END, 'depends'=> @app\assets\AppAsset::ClassName()]); ? > <div id="form"> </div> <script type='text/javascript'> var vue_form_template = <? =json_encode($form_template)? >; var vue_form_data = <? =json_encode($form_data)? >; var vue_form_mounted= <? =json_encode($form_mounted)? > var form_temp_methods= <? =json_encode($form_methods)? >; var vue_form_method = {};function generateMethods() { for (let key in form_temp_methods) { vue_form_method[key] = function() {arguments console.log(arguments) by default;eval(form_temp_methods[key]) } }; } generateMethods() </script> Copy the code
FormWidget
<? php namespace app\components\form; use yii\base\Widget; use yii\helpers\Html; use app\assets\AppAsset; class FormWidget extends Widget { public$form_template = ' '; public $form_data = []; public $form_mounted; public $form_methods; public function init() { } public function run() { return $this->render('FormView'['form_template'= >$this->form_template, 'form_data'= >$this->form_data, 'form_mounted'= >$this->form_mounted, 'form_methods'= >$this->form_methods, ]); } public functionGetViewPath () // This function defines the path of the widget view {return '@app/components/form'; }}Copy the code
-
Used in index.php
<? =FormWidget::widget([// HTML passed into controller, similar to <el-button></el-button>'form_template'= >$form_template.'form_data'= >$form_data.'form_mounted'= >$form_mounted.'form_methods'= > ['closeForm'= >' Table.table_span = 20; this.form_data.form_is_show = false; '.'saveForm'= >' this.closeForm() ' ] ])?> Copy the code
-
Problems with the first edition
- Widget communication, such as a tree widget and a form widget, requires that the VUE instance of the tree be able to manipulate the VUE instance of the form when THE form widget needs to be updated when I click on a node of the tree
- Vue_form_method is a method attribute assigned to vue after traversing form_methods, but such traversal cannot specify parameters. For example, element’s tree has an event called Node-click, which passes three parameters by default. This cannot be specified in form_methods.
- Some new ideas from Boss
- Broadcast, that is, all components on the page can listen for events. When an event occurs, the component that listens for the event can react accordingly
- Global variables, such as two components introducing the same variable, change the two components’ data accordingly
-
The solution
- Assign a vue instance to a variable, such as
var Tree = new Vue()
, then other components can access the Tree’s properties using tree.example_data - Using the arguments,
var node = arguments[0]
To access the parameters. I personally don’t think it’s a good idea, but I can’t think of a better solution - For the broadcast problem, I wrote an event_bus widget, which is just a pure vUE instance that each widget uses
EventBus.$on('click', function() {})
Method to listen for events,EventBus.$emit('click')
Method to trigger an event. - If the global variable is an object or array, the data can change as the variable changes
- Assign a vue instance to a variable, such as
to be continue…