1. 程式人生 > >Yii2 ActiveForm小部件渲染過程

Yii2 ActiveForm小部件渲染過程

bubuko 有一個 ini 客戶端驗證 我們 tar 加載 bsp 對象

問題:

(1)ActiveForm::begin()做了什麽,ActiveForm::end()做了什麽,中間echo的ActiveForm::field()內容是如何渲染的;

(2)我們在ActiveRecord模型類的rules規則裏定義的驗證方法如何在客戶端頁面同樣生效的;

首先看Yii2 ActiveForm小部件渲染過程

技術分享圖片

1. yii\widght\ActiveForm::begin($config);

這裏實例化了ActiveForm對象,通過 __construct() 調用 init(),在這裏生成小部件的唯一id:getId(),打開輸出緩沖:ob_start();ob_implicit_flush(false);

2. 小部件實例化後就可以通過它的field()方法生成表單內容控件

echo $form->field($model,$attribute,$options);//生成默認的textInput控件

echo $form->field($model,$attribute,$options)->radio();//生成radio控件

這裏有一個關鍵的地方:ActiveField對象在ActiveForm::field()方法中被創建,而其內容的渲染源自於`echo`的調用會觸發ActiveField的__toString()魔術方法,這裏調用了ActitveField的render()方法通過ActiveField的begin()與end()方法渲染完整內容。
(1) ActiveField::begin()會通過ActiveField::getClientOptions()方法獲得指定屬性的詳細信息,包括驗證規則,並填充到對應$form的$attributes屬性中。
(2) 這裏關鍵在於ActiveField::getClientOptions()做了什麽:
1)通過當前$model判斷該$attribute是否有效;
2)如果開啟了客戶端驗證,則通過$model->getActiveValidators($attribute)獲得與當前$attribute當前scenario相關的驗證規則;
3)遍歷上一步獲得的驗證規則,通過每個驗證器(yii\vaidators\Validator的子類的實例)的clientValidateAttribute()方法獲得對應驗證規則的客戶端驗證的js內容;
4)填充$attribute的id,name等信息後,將上一步獲得的所有客戶端驗證js內容組合到一個完整的js匿名函數中;
5)返回上述所有步驟獲得的信息,交由begin()存入對應$form的$attributes中。

(3) 當所有ActiveField都執行完畢,就來到了ActiveForm::end(),

1)通過ob_get_content()拿到上述所有field的輸出;

2)如果開啟了客戶端驗證,則會註入ActiveFormAsset資源包內容,並註入yii.activeForm.js的yiiActiveForm($attributes, $options);js內容。

(4) 頁面加載時會執行上面註入的yiiActiveForm.init()方法。

由於傳入的$attributes參數包含了所有$attribute的詳細描述與客戶端驗證需執行的js驗證方法,在yii.activeForm.js中就可以實現對各個屬性的事件監聽並觸發對應的驗證邏輯。

Yii2 ActiveForm小部件渲染過程