Heim > php教程 > php手册 > Yii2的相关学习记录,alert等美化、confirm异步、session中的flash及小部件的使用(六),yii2confirm

Yii2的相关学习记录,alert等美化、confirm异步、session中的flash及小部件的使用(六),yii2confirm

WBOY
Freigeben: 2016-06-13 08:42:18
Original
1169 Leute haben es durchsucht

Yii2的相关学习记录,alert等美化、confirm异步、session中的flash及小部件的使用(六),yii2confirm

呃,系统自带的alert、confirm等弹出框实在是难看,作为一个颜控,这能忍?

这里我用的是kartik-v/yii2-dialog,这个是基于bootstrap3-dialog这个来做了一些常用alert、confirm和dialog的小部件封装,当然了,本质上还是bootstrap3-dialog,可以用原生的方法,原生方法的用法点这里,而bootstrap3-dialog又是基于bootstrap3的modals做的封装。嗯,基本关系就是这样。在搜索这个相关知识时,经常会看到有人提到bootbox,这个同样是流行的一个美化插件,基本原理类似,用法稍微不同,在packagist搜索yii2 bootbox会发现也有人为Yii2做了集成(或者自己集成也行,后面会讲到),同样值得推荐。

按照说明安装,最好是按照github的说明,因为最新的一般都会在这里先更新。composer中要用@dev。可以看这里的说明,如果不成功,先composer self-update,再试下,当初安装时也是各种报错不行,后来突然就好了。稍微注意的是confirm,dialog调用时要求必须写回调,否则就报错。

还是蛮漂亮的。但是像是Yii框架Gridview自带的confirm(像是删除按钮),点击时还是原生的,因为它的源码就是用的confirm命令,好在Yii框架提供了方法,可以让我们覆盖confirm方法。具体可如下操作:

1、我们可以先看下在vendor/yiisoft/yii2/assets/yii.js文件中的confirm方法:注释中就可以看到,可以用yii.confirm来重写此设置。

 <span>/*</span><span>*
    * Displays a confirmation dialog.
    * The default implementation simply displays a js confirmation dialog.
    * You may override this by setting `yii.confirm`.
    * @param message the confirmation message.
    * @param ok a callback to be called when the user confirms the message
    * @param cancel a callback to be called when the user cancels the confirmation
    </span><span>*/</span><span>
    confirm</span>: <span>function</span> (message, ok,<span> cancel) {
        </span><span>if</span><span> (confirm(message)) {
            </span>!ok ||<span> ok();
        } </span><span>else</span><span> {
            </span>!cancel ||<span> cancel();
        }
    }</span>,
Nach dem Login kopieren

2、那我们就重写,可以在backend/web/js中新建confirm.js文件,然后重新,可参照此文章,这是设置bootbox的,而且版本有点过时,不过下方的评论有最新方法。而我们的设置与此原理是一致的,只不过是改成kartik-v/yii2-dialog所需求的参数样式:

yii.confirm = <span>function</span> (message, ok,<span> cancel) {
    krajeeDialog</span>.confirm(message,<span>function</span><span>(data){
        </span><span>if</span><span> (data) {
            </span>!ok ||<span> ok();
        } </span><span>else</span><span> {
            </span>!cancel ||<span> cancel();
        }
    });
    </span><span>//</span><span> confirm will always return false on the first call
    // to cancel click handler</span>
    <span>return</span> <span>false</span><span>;
}</span>
Nach dem Login kopieren

3、我们需要注册此js,可以在backend/assets/Appasset.php中添加上方的js文件:

<span>class</span> AppAsset <span>extends</span><span> AssetBundle
{
    </span><span>public</span> <span>$basePath</span> = '@webroot'<span>;
    </span><span>public</span> <span>$baseUrl</span> = '@web'<span>;
    </span><span>public</span> <span>$css</span> =<span> [
        </span>'css/site.css',<span>
    ];
    </span><span>public</span> <span>$js</span> =<span> [
        </span>'js/confirm.js',<span>//</span><span>就是这里了</span>
<span>    ];
    </span><span>public</span> <span>$depends</span> =<span> [
        </span>'yii\web\YiiAsset',
        'yii\bootstrap\BootstrapAsset',<span>
    ];
}</span>
Nach dem Login kopieren

这样一来,在点击删除按钮便会发现可以调用了:

由于我们用的是kartik-GridView,它的两个功能展示全部记录和导出csv等的提示,都是用的原生的confirm,强迫症的我们能忍吗?好吧,我忍了,这里只给出改的思路,尤其是只懂基础js的我来说,先把时间放在其它地方吧。

在改之前,首先我们需要明确kartik-v/yii2-dialog的confirm(bootbox同样)和原生confirm的不同。原生confirm是同步的,而kartik-v/yii2-dialog的confirm方法是异步回调的。这导致原生的confirm可以直接这样写:

<span>function</span><span> abc(){
    </span><span>return</span> window.confirm('123');<span>//</span><span>confirm点击确认返回true,取消返回false,不点击就等着用户点击    </span>
<span>}
</span><span>if</span><span>(abc()){
    alert(</span>'456');<span>//</span><span>点击是,会弹出alert弹窗</span>
}
Nach dem Login kopieren

而如果你用kartik-v/yii2-dialog的confirm也这样写,则永远不会弹窗,因为是异步回调的,不会去等你点击。

<span>function</span><span> abc(){
    krajeeDialog.confirm(</span>'123',<span>function</span><span>(result){
        </span><span>if</span><span>(result){
            </span><span>return</span> <span>true</span><span>;
        }</span><span>else</span><span>{
            </span><span>return</span> <span>false</span><span>;
        }
    });
}
</span><span>if</span><span>(abc()){
    alert(</span>'456');<span>//</span><span>由于是异步回调,所以不管点不点都不会弹窗</span>
}
Nach dem Login kopieren

可能有人会想(比如我)这样写行不行?不行,不支持这样的写法,bootstrap3-dialog中这样写返回的是窗口有没有open。

<span>if</span>(krajeeDialog.confirm('123',<span>function</span><span>(result){}){
    </span><span>return</span> <span>true</span><span>;
}</span><span>else</span><span>{
    </span><span>return</span> <span>false</span><span>;      
}</span>
Nach dem Login kopieren

所以要想在kartik-v/yii2-dialog的confirm中执行alert,只能将alert放在回调函数中:

<span>function</span><span> abc(){
    krajeeDialog.confirm(</span>'123',<span>function</span><span>(result){
        </span><span>if</span><span>(result){
            alert(</span>'456'<span>);
        }</span><span>else</span><span>{
           </span><span>//</span><span>do something</span>
<span>        }
    });
}</span>
Nach dem Login kopieren

以上的不同,再加上是在vendor中修改有违原则啊(拿出来很费劲,又是继承什么的,而导出csv的js没找到类似yii.js那样覆盖的方法,只能重新写引入什么的),也是我不想改源码的原因。坑爹。好吧,下面继续说怎么改:

1、{toggleData}显示全部记录,它的调用confirm是在vendor/kartik-v/yii2-grid/GridView.php中的getToggleDataScript方法,我们修改return就可以:

<span>$url</span>=Url::<span>current</span>([<span>$this</span>->_toggleDataKey => <span>$tag</span>]);<span>//</span><span>先定义需要跳转的url</span>
<span>return</span> "\$('#{<span>$this</span>->_toggleButtonId}').on('{<span>$event</span><span>}',function(e){
    e.preventDefault();//先阻止点击事件
    krajeeDialog.confirm('{</span><span>$msg</span><span>}',function(data){
        if (data) {
            window.location.href='{</span><span>$url</span><span>}';//点击是则跳转
        }
    });
    //下面这条是原来的方法
    // if(!window.confirm('{</span><span>$msg</span><span>}')){e.preventDefault();}
});</span>";
Nach dem Login kopieren

2、{export}中的导出提示,是在vendor/kartik-v/yii2-grid/assets/js/kv-grid-export.js中:这个就麻烦了,感觉需要重写关联的notify方法和listenClick方法。谁写完了,麻烦告诉一声吧。

kvConfirm: <span>function</span><span> (msg) {             
    </span><span>try</span><span> {
        </span><span>return</span> window.confirm(msg);<span>//</span><span>调的这个</span>
<span>    }
    </span><span>catch</span><span> (err) {
        </span><span>return</span> <span>true</span><span>;
    }
}</span>
Nach dem Login kopieren

上面就这样吧,下面说下session中的flash,我们一般创建完成等操作时,需要给点提示是完成了还是怎么着。在Yii中有自带flash方法来实现,可点击这里查看,其实在adminLTE这个后台框架中已集成了Alert小部件,我们可以在backend/views/layout/content.php中发现此小部件的调用,这是我们只需要在controller中添加setFlash方法,那么就能在view中接受到:

  <span>public</span> <span>function</span><span> actionCreate()
    {
        </span><span>$model</span> = <span>new</span><span> User();

        </span><span>if</span> (<span>$model</span>->load(Yii::<span>$app</span>->request->post()) && <span>$model</span>-><span>save()) {
            </span><span>$session</span> = Yii::<span>$app</span>->session;<span>//</span><span>session</span>
            <span>$session</span>->setFlash('success', '创建成功');<span>//</span><span>添加flash</span>
            <span>return</span> <span>$this</span>->redirect(['index'<span>]);
        } </span><span>else</span><span> {
            </span><span>return</span> <span>$this</span>->render('create',<span> [
                </span>'model' => <span>$model</span>,<span>
            ]);
        }
    }</span>
Nach dem Login kopieren

捕捉到的:(adminLTE的alert样式颜色就是这么深,而Yii框架自带的颜色虽然浅,但是与此后台框架的颜色也不搭配)

进一步扩展就是,如果是成功的提示,那我5s后可以隐藏,那可以这样设置,在backend/views/layout/content.php中添加下面渐隐的js代码

<?php <span>//</span><span>这是一段,在显示后定里消失的JQ代码</span>
    <span>$this</span>->registerJs("<span>
        $('.alert-success').animate({opacity: 1.0}, 5000).fadeOut('slow');
    </span>"<span>);  
</span>?> 
Nach dem Login kopieren

唉?为什么突然说到flash,明显前后文不统一吗,差评!主要是,既然有alert形式的flash,那当然也可以用弹窗的方式来展示啊。kartik-v/yii2-dialog虽然有alert、dialog功能,但是在这里都和我想要的不太一样,所以我们直接调用原生的方法来写,主要的方法是这样:(下面有详细封装)

<span>var</span> dialogShow=<span>BootstrapDialog.show({
    type:BootstrapDialog.TYPE_SUCCESS, 
    title:</span>'提示消息'<span>,
    message:</span>'创建成功,3s后自动关闭'<span>,
    size:BootstrapDialog.SIZE_SMALL,
    buttons:[
        {
            label: </span>'关闭'<span>,
            action: </span><span>function</span><span>(dialogItself){
                dialogItself.close();
            }
        }
    ]
});</span>
Nach dem Login kopieren

我们当然可以直接在index.php中写,但是东西有点多,最好封装一下,好吧,那就参照Alert来写一个Popup的widget来用吧:(一些介绍点这里),在common/widgets中新建Popup.php,直接贴代码吧。由于只是注册js,没有返回值什么的,所以没有用到run()方法。

1 php 2 3 namespace common\widgets; 4 5 class Popup extends \yii\bootstrap\Widget 6 { 7 /** 8 * 样式数组 9 * @var [type] 10 */ 11 public $popupTypes = [ 12 'default' => 'BootstrapDialog.TYPE_DEFAULT', 13 'info' => 'BootstrapDialog.TYPE_INFO', 14 'primary' => 'BootstrapDialog.TYPE_PRIMARY', 15 'success' => 'BootstrapDialog.TYPE_SUCCESS', 16 'warning' => 'BootstrapDialog.TYPE_WARNING', 17 'danger' => 'BootstrapDialog.TYPE_WARNING' 18 ]; 19 /** 20 * 尺寸数组 21 * @var [type] 22 */ 23 public $sizeTypes=[ 24 'nomal'=>'BootstrapDialog.SIZE_NORMAL', 25 'small'=>'BootstrapDialog.SIZE_SMALL', 26 'wide'=>'BootstrapDialog.SIZE_WIDE', 27 'large'=>'BootstrapDialog.SIZE_LARGE' 28 29 ]; 30 /** 31 * 标题 32 * @var [type] 33 */ 34 public $title; 35 /** 36 * 尺寸 37 * @var [type] 38 */ 39 public $size; 40 41 public function init() 42 { 43 parent::init(); 44 //默认标题 45 if ($this->title === null) { 46 $this->title = '消息提示'; 47 } 48 //默认样式 49 if ($this->size===null || !isset($this->sizeTypes[$this->size])){ 50 $this->size='small'; 51 } 52 53 $session = \Yii::$app->session; 54 $flashes = $session->getAllFlashes(); 55 56 $view = $this->getView(); 57 58 foreach ($flashes as $type => $data) { 59 if (isset($this->popupTypes[$type])) { 60 $data = (array) $data; 61 foreach ($data as $i => $message) { 62 $view->registerJs(" 63 var dialogShow=BootstrapDialog.show({ 64 type:".$this->popupTypes[$type].", 65 title:'".$this->title."', 66 message:'".$message."', 67 size:".$this->sizeTypes[$this->size].", 68 buttons:[ 69 { 70 label: '关闭', 71 action: function(dialogItself){ 72 dialogItself.close(); 73 } 74 } 75 ] 76 }); 77 "); 78 // 如果是成功,需要增加3s后自动关闭,其余警告等则不需要 79 if($type=='success'){ 80 $view->registerJs(" 81 setTimeout(function(){ dialogShow.close() }, 3000); 82 "); 83 } 84 } 85 86 $session->removeFlash($type); 87 } 88 } 89 } 90 } 太长隐藏

然后在backend/views/layout/content.php引用小部件:

<span>use</span><span> common\widgets\Popup;
</span><?= Popup::<span>widget([
    </span>'title'=>'消息',
    'size'=>'small'<span>//</span><span>参数不写会有默认值</span>
]) ?>
Nach dem Login kopieren

 看下效果:如果是success,则会自动消失。

那弹出框Popup和提示Alert最大区别是,当存在addFlash方法时,Alert可以依次排列显示多个,而弹出框Popup则会重复覆盖显示,不太友好。当然了在不用addFlash方法时弹出框Popup的显示更漂亮醒目。

好了,就这样,睡觉先!

Quelle:php.cn
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Empfehlungen
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage