Yii CJSON::对javascript函数进行编码

Yii CJSON::对javascript函数进行编码,yii,json,Yii,Json,我将jQuery小部件工厂(jQuery小部件)用于我的js小部件 $.widget('cool.someWidget', { options: { onSomething: null } // other js code }); 通常从您编写的js运行小部件 $(selector).someWidget({ onSomething: function() { ..... } }); 在Yii中,我使用CJSON::encode编译所有

我将jQuery小部件工厂(jQuery小部件)用于我的js小部件

$.widget('cool.someWidget', {
     options: {
         onSomething: null
     }
     // other js code
});
通常从您编写的js运行小部件

$(selector).someWidget({
    onSomething: function() { ..... }
});
在Yii中,我使用CJSON::encode编译所有初始化属性,包括onSomething事件

echo CJSON::encode(array(
    'onSomething' => 'function() {....}',
));
但是,由于转换(CJSON),它将函数(){…}转换为字符串,因此在文档中写入以下内容

$(selector).someWidget({
    onSomething: "function() { .... }"
});
因为当我调用this.\u触发器('onSomething')时,onSomething实际上是一个字符串,它不会运行代码


我只有在“生成”视图时才遇到这个问题,而不是Ajax请求(我在系统中处理的方式不同)。有没有什么“正常”的方法可以让Yii在文档中实际编写带有引号的函数?

我编写了下面的函数,它完全符合我的要求。不过,如果有一些土生土长的Yii解决方案,我真的很想知道

public function encodeOpts($data, $jsCode = null) {
    $rVal = CJSON::encode($data);

    if ($jsCode == null)
        return $rVal;

    foreach($jsCode as $key => $code) {
        $codeEntries[] = "\"{$key}\": {$code}";
    }

    return substr_replace($rVal, ', ' . implode(', ', $codeEntries), -1) . '}';
}

我认为这个问题的前提是有缺陷的,如果你完全回避这个问题会更好

这里有什么问题?不能将JavaScript代码作为PHP字符串提供

你为什么要这么做?我不认为存在令人信服的理由。JavaScript代码应编写为JavaScript代码;把它写成字符串更糟糕

很可能您希望将一组可用的选项作为PHP变量传递给插件,令人兴奋的是,以相同的方式传递所有选项(包括那些函数)似乎是个好主意

但是还有另一种方法,这是出于礼貌:对所有标量(字符串、数字)使用
CJSON::encode
,对回调使用纯JavaScript

$(selector).someWidget($.extend(
    <?php echo CJSON::encode(array(/* no functions here, just scalars */));?>,
    { // and now, back in JavaScript-land, code follows:
        onSomething: function() { ..... }
    }
));
$(选择器).someWidget($.extend(
,
{//现在,回到JavaScript领域,代码如下:
onSomething:function(){….}
}
));

实际上有一种内置方法可以防止encode函数将函数声明用引号括起来,您应该在函数声明之前添加js:

CJavaScript::enocde(array(
   'prop'=>'value',
   'callback' => 'js:function(){}'
))
我是这样解决的:

if ($this->user_options !== null && is_array($this->user_options))
{
    $reqs = CJavaScript::encode(
        array_merge(
            $this->user_options,
            array(
                // adding a default callback to options 
                'onLoad' => 'js: function() {$("#info").text("Hi")}'
                )
            )
        );
}

注意:
js:
仅适用于
CJavaScript
而不适用于
CJSON

能够做到这一点感觉很好。Yii具有CJSON,因此它可以正确地将所有字符串编码为字符串。但有时,你需要在一个链中“绑定”插件,就是在另一个插件发生事件时运行一个插件的函数。至于我为什么要用PHP(Yii)来做这件事?因此,我的小部件可以正确地写入所有内容,而不会受到选择和绑定开销的影响。这应该是答案,imho@Jon:我们在这里讨论的是小部件。可重用的代码片段,Yii开发人员可以插入到他们的应用程序中。在这种情况下,您希望如何传递Javascript代码?正如你所看到的,一个令人信服的理由确实存在。现在呢?你把帽子扔进去,当你被一个高质量的论据击败时,你甚至不愿意回应?多么有礼貌…@trejder:精明的读者会注意到,尽管问题中特别引用了jQuery小部件,但Yii小部件却没有。当然,这里提到了Yii,但问题中没有提到Yii小部件。上面的评论甚至没有提到Yii小部件。下面OP的“最终解决方案”中也没有类似的内容。所以,在到处指责别人之前,也许应该先检查一下你的假设。我想这就是你要找的: