淘宝KISSY前端框架

KISSY是由阿里前端团队发起并维护的国产javascript框架,在阿里网站比如淘宝网、天猫、聚划算中大量使用,经过近五年的发展(KISSY诞生于2009年10月26日),已经是比较成熟的解决方案,也是为数不多存活下来的国产javascript框架 ——KISSY

KISSY 是一款跨终端、模块化、高性能、使用简单的 JavaScript 框架。除了完备的工具集合如 DOM、Event、Ajax、Anim 等,它还提供了经典的面向对象、动态加载、性能优化解决方案。作为一款全终端支持的 JavaScript 框架,KISSY 为移动终端做了大量适配和优化,让你的程序在全终端均能流畅运行。

KISSY is a powerful javascript framework for building cross end web application such as desktop, mobile and pad.

使用 KISSY 1.4

  • 下载 KISSY 1.4.8
  • 通过 cdn 使用 <script src="//g.alicdn.com/kissy/k/1.4.8/seed-min.js" charset="utf-8"></script>
  • npm 安装 KISSY: npm install kissy@1.4.8
  • bower 安装 KISSY: bower install kissy#1.4.8

模块系统

CommonJS、AMD、CMD 三者的关系和区别,是前端经典的面试题目哦。

CommonJS是非常广泛的规范,包含了大量的内容,不止局限在浏览器端(比如Node.js),AMD、CMD都是其模块系统部分的子集,在CommonJS的wiki中找到践行CommonJS的javascript框架。

CommonJS 一个模块的代码 test.js:

var $ = require('jquery');
exports.test = function () {}; 将 test 方法暴露给外部使用。

上面的代码明显没办法直接在浏览器端运行,所以就有了AMD 模块系统规范,可以保证模块文件可以在浏览器端正常执行。

RequireJS 就是AMD 模块系统规范的实现者:

define(['jquery'] , function ($) {
    return function () {};
});

除了 AMD 还有 CDM 模块系统规范,SeaJs是其实现者:

define(function(require, exports) {
    // 获取模块 a 的接口
    var a = require('jquery');
    exports.test = function () {};
});

相对于AMD,个人更推崇CMD规范,写法风格上更接近 CommonJS ,更接近 NodeJs 的写法。

KISSY的模块系统遵循的是KMD规范:

KISSY.add(function(S,Node){
    var $ = Node.all;
    return function(){};
},{requires:["node"]});

模块使用KISSY.add()包裹,现在已经不推荐使用该风格(Kissy文档和gallery存在大量KMD写法的代码,请无视),Kissy已经支持commonjs的风格:

KISSY.add(function(S,require,exports,module){
    var $ = require('node');
    exports.test = function () {};
});

选择器

KISSY.add('xx',function(S){
    var $ = S.Node.all;              //$变量等同于jquery写法使用了
      var $test = $('#J_Test');
      var js = $test[0];             //也可以转换为js原生节点

      var $one = S.Node.one('li');   //只获取一个节点

}, {requires:[
     'node' //node 包括 dom , event , anim 模块的所有功能,
            //推荐采用 Node 模块, 你只需要把 KISSY.all 看做 jquery 中的 $ 就可以了, 链式操作你会喜欢的!
   ]});

S.Node.all(selector).item(0) 可以等价于 S.Node.one(selector)

建议:操作DOM前请通过length判断节点是否存在,这是前端工程师良好的习惯

var $child = $(".J_Parent .J_Child");    //获取 .J_Parent 节点下的 .J_Child 节点  length将会获取2个结果
var $child = $(".J_Parent > .J_Child");  //获取子节点呢  length将会获取1个结果
var $first = $(".J_Parent > li:first-child"); //使用 css3 的选择器即可,从多个子孙节点精确选取
var $two = $(".J_Parent > li:nth-child(2)"); //index 从 1 开始
var $last = $(".J_Parent > li:last-child");
var $checkbox = $('input:checked');         //获取被选中的节点
var $text=$('.J_Text').text($checkbox.val());
var $p = $('.J_Brother + p');               //伪类选择器
var $disabled = $('.J_Checkbox:disabled');  //获取被禁用的节点
var $p = $('li:not(.J_Brother)');           //获取非的class=J_Brother的<li>节点

DOM操作

KISSY操作DOM的模块是node,该模块的api与jquery非常的相似,如果您熟悉jquery,那么使用kissy的node模块就毫无障碍。

想要操作节点,先要获取节点,如何获取呢?让我们回想下css中有个选择器的概念,通过选择器样式可以针对节点起作用的,而node模块中也是通过选择器来寻找节点的。

以下的这些方法, filter() , test() , clone() , empty() , replaceWith() , hasClass(), addClass(), removeClass(), replaceClass(), toggleClass(), removeAttr(), attr(), hasAttr(), prop(), hasProp(), val(), text(), css(), toggle(), offset(), scrollIntoView(), parent(), index(), next(), prev(), first(), last(), siblings(), children(), contains(), html(), remove(), data(), removeData(), hasData(), unselectable(), contains(), innerWidth(), innerHeight(), outerWidth(), outerHeight(), on(), detach(), fire()

  1. 如果返回值为单个节点或节点数组, 则包装为 NodeList
  2. 如果返回值为 undefined , 则返回调用者 NodeList 对象
  3. 其他, 直接返回
$('.J_Wrapper').append($('<div>我是新节点</div>'));
$('.J_Wrapper').prepend($('<div>我是新节点</div>'));  //返回的值是 $('.J_Wrapper') NodeList 对象
$('#J_Two').insertBefore($('#J_One')).text('我是第二个节点,但我要当第一个');
$('.J_ChangeBg').style('background-color','green');   //css()和style()在设置样式值上等价
$('.J_ChangeBg').css({'background-color':'black','color':'white','font-size':'16px'})
$('.J_Input').attr('disabled',true);
$('.J_Input').attr('data-id');  //获取的是attribute
$('.J_Input').prop('disabled'); //返回true 获取的是property
var has = $('.lists').test('li');//判断是否符合过滤条件
var $css = $('.lists').filter('.css');//只取class=css的节点
var $html = $('.lists').filter(function(item){
              if($(item).text() === 'html'){
                return true;
              }
            }); //$html为dom集合
$('.J_Children').children('li') //获取 .J_Children 下的所有子节点
$('.J_Children').all('li')      //all() 方法会将孙节点的 li 也会捞出来
var $ul = $('.J_Css').parent(); //.J_Css 节点来获取父节点 ul
var $prev = $('.J_Css').prev(); //获取符合选择器的上一个,next()下一个节点
var $lis = $('.li').siblings(); //获取.li下同级节点.不包括.li自己
$('.J_Children').show()         //显示div
S.Node.one('.hello').clone(true).appendTo('.goodbye');//为了阻止原来的元素移动,而插入复制版本
$('.J_Children').val()  //返回元素所的value值. 无值时返回空字符串
$('.J_Children').text() //由参数获取文本值.无为设置文本值

事件

事件是javascript中非常重要的概念,跟jQuery一样,kissy也封装了全兼容浏览器的事件api:event模块,而且API非常相似。

使用on(eventName,handler)绑定事件:

  • eventName 事件名称,常用的有clicktap(手机页面的点击)、focusin(获取焦点)、focusout(失去焦点)、mouseenter(鼠标移入)、mouseleave(鼠标移出)等
  • handler 事件处理器,留意ev的数据
$('.J_Target').on('click',function(ev){
      //ev.target 指向被点击的节点
      var $target = $(ev.target);
      var $currentTarget = $(ev.currentTarget);
      //永远指向事件源$('.J_Target')
      $('.J_TargetText').text('target:'+$target.attr('class'));
      $('.J_CurrentTargetText').text('currentTarget:'+$currentTarget.attr('class'));
    })
$('.J_Hover').on('mouseenter mouseleave',function(ev){
    var $target = $(ev.target);
    if(ev.type === 'mouseenter'){
        $target.text('mouseenter');
    }else if(ev.type === 'mouseleave'){
        $target.text('mouseleave');
    }
})

解除事件绑定

可以给节点的一个事件类型绑定多个事件监听器,如果想要解绑某个事件监听器,使用detach的第二个参数:

function clickHandler(ev){
    //do Something
}
$('.J_Target').on('click',clickHandler);
$('.J_Target').detach('click',clickHandler);

事件代理

假设我们有这样的需求:动态创建一个段落到页面中,点击段落,又新增一个段落,如何实现呢?

每次添加个节点,我们都要绑定个click事件,非常蛋疼,有没有一种更好的方式呢?

delegate(eventType,selector,handler)

  • eventType 事件类型
  • selector 子孙节点选择器
  • handler 事件监听器

使用delegate() 将节点的事件统一委托给父节点,这样可以保证动态节点的节点,依旧存在事件监听,作用域是在父节点之内。

$( "body" ).delegate( "click","p", function(ev) {
      $(this).append( "<p>添加一个段落</p>" );
      //我们将body下所有p的点击事件都委托给body
  });

解除代理事件绑定$( "body" ).undelegate( "click","p");

阻止事件行为

方法ev.stopPropagation();会阻止事件冒泡,此方法名太长(记不住( ⊙ o ⊙ )!),建议使用halt()方法。

halt()的作用是停止事件冒泡,同时停止默认行为,比如a标签的跳转、button的提交等。

如果你只想阻止默认行为,而不想阻止事件冒泡,可以使用 preventDefault() 方法

触发表单事件

表单元素会带有默认事件,常用的有:

  • submit:表单提交事件
  • blur:失去焦点事件
  • focus:获得焦点事件
  • change:值改变触发的事件,常用于选择框
  • select:比如输入框选中文字后触发

kissy没有jQuery触发这些事件的门面方法,比如$('input').blur(),但可以通过fire()方法来触发表单事件,比如:

$('input').fire('blur'); fire()可以触发任何以上常用等浏览器支持的事件

特殊事件

比如 clickmouseentermouseleave,除此之外还有如下鼠标事件,kissy也是支持的:

  • dblclick:双击事件
  • mousedown:鼠标按下事件
  • mousemove:鼠标移动事件
  • mouseup:鼠标放开事件
  • mouseover:鼠标经过事件
  • mouseout:鼠标移开事件

假设如下嵌套结构:

<div class="out J_Over">
    <span>over</span>
    <div class="in"></div>
</div>
var i = 0;
$( ".J_Over").on('mouseover',function(ev){
    var $target = $(ev.currentTarget);
    if(ev.type==='mouseover'){
        i++;
        $target.all('span').text('鼠标经过次数:'+i);
    }
});

in节点是over节点内部,但在in节点边缘进出,居然也触发了mouseover事件!

为了解决这个问题,就有了mouseenter事件:

var n = 0;
$( ".J_Enter").on('mouseenter',function(ev){
    var $target = $(ev.currentTarget);
    if(ev.type==='mouseenter'){
        n++;
        $target.all('span').text('鼠标经过次数:'+n);
    }
});

mouseenter(鼠标经过)mouseleave(鼠标移开)是kissy为了兼容而多出的一种事件形式

监听keyup事件:键弹起触发的事件

$('.J_Input').on('keyup',function(ev){
    var val = $(ev.target).val();
    $('.J_Count').text(val.length);
})

有时我们需要获取用户按下的键码来做些过滤处理:

$('.J_Input').on('keyup',function(ev){
    var code = ev.which;
    //空格键
    if(code === 32){
        //...
    }
})

io网络

kissy的io模块,相当于jQuery的ajax功能,用于异步获取内容。

io 的配置项非常丰富,api和jQuery非常相似,如果嫌配置麻烦,建议使用io的门面方法,比如get()、post()getJSON()jsonp()`

异步调用github的接口,获取一个仓库的信息。

var io = require('io');
io.jsonp('https://api.github.com/repos/minghe/auth',function(authData){
    $('body').append('<p>'+authData.name+':'+authData.description+'</p>');
});

io.jsonp(url,data,callback)是io()的门面方法,用于快速发起jsonp请求。

  • url 接口url
  • data 非必须,接口传参,会拼接到url的?后
  • callback 请求成功后执行后的回调

最后的请求地址:https://api.github.com/repos/minghe/auth?_ksTS=1419861634311_19&callback=jsonp20

  • _ksTS 是kissy自动加上的时间戳,防止请求缓存
  • callback 是jsonp使用的回调函数名,在不指定的情况下,kissy会自动生成。
io({
    type:"get",
    dataType: "jsonp",
    url: 'https://api.github.com/repos/minghe/auth',
    data: {},
    success: function(authData){
         $('body').append('<p>'+authData.name+':'+authData.description+'</p>');
     }
});
  1. type 请求类型,可以设置为get、post,留意jsonp不是请求类型,jsonp是get请求类型
  2. dataType 请求返回的数据类型,常用的有 jsonp、json、xml、html、text、script
  3. url 接口地址
  4. data 接口传参
  5. success 请求成功后执行的回调
$('.J_Submit').on('click',function(ev){
    ev.halt();
    io.post('3.json',{
        user: $('.J_User').val(),
        email: $('.J_Email').val()
    },'json').then(function(result){
        var data = result[0];
        if(data.success){
            $('body').html('异步post数据成功!');
        }
    })
})

post(url , [ data , callback , dataType ] ):异步提交表单数据到服务器端

  • url (string) – 请求地址
  • data (Object|string) – 请求附带的参数,参见 data .
  • callback (function) – 请求成功后的回调,参见 success .
  • dataType (string) – 传到回调函数作为参数的数据类型,参见 dataType

IO常用的事件有:

  • send 事件:请求发送前触发
  • complete 事件:请求完成后触发(不管是请求失败还是成功都会触发)
  • success 事件:请求成功后触发
  • error 事件:请求失败后触发

模板xtemplate

kg/xtemplate 拥有非常优异的性能,不输于(甚至优于)主流的模板引擎,比如HandlebarsJSejsnunjucksartTemplate

KISSY1.4.X使用的是3.3.3版本的xtemplate,带KISSY.add()包裹,3.3.3以上的版本是KISSY5使用的,带modulex.add(),比如3.4.1。

xtemplate(新)也支持作为服务器端模板引擎(比如Node.js ,支持express和koa)

编译模板

编译器模块为xtemplate,kissy1.4.x请使用3.3.3的版本:

如果你使用gulp构建(建议使用),请使用gulp插件:gulp-xtemplate

gulpfile.js的写法参考 bee

var XTemplate = require('xtemplate');
var gulpXTemplate = require('gulp-xtemplate');
var src = "./src";
gulp.task('xtpl',function(){
    return gulp.src(src+'/**/*.xtpl')
        .pipe(gulpXTemplate({
            wrap: 'kissy',
            XTemplate: XTemplate
        }))
        .on('error',function(e){
            console.log(e);
        })
        .pipe(gulp.dest(src));
});

xtpl 任务会构建src目录下所有.xtpl文件,所以xtemplate模板文件必须是xtpl后缀。

wrap: 'kissy' 会给编译后的模块js文件加上KISSY.add() 包裹,如果是KISSY5的代码,不用传参。

wrap: 'none' 将不带任何包裹函数。

任务运行后,会生成2个文件,参考 bee ,content.xtpl生成 content.jscontent-render.js,content.js是编译后模板模块,而content-render.js是快速渲染模板的门面方法。

Kissy.add('notedown/av',function(S,XTemplateRuntime,avView){
            //data json对象数据
            //avView 为编译后的模板 例如上 content.xtpl生成content.js
            var html = new XTemplateRuntime(avView).render(data);
            $('body').append(html);
}, {requires:[
     "kg/xtemplate/3.3.3/runtime",
     'notedown/av-view'
 ]});

本博客就是使用编译后模板.kg/xtemplate/3.3.3/runtime 才几十行的代码.容量远比其它模板引擎小.移动端性能好

语法

如果你希望输出最原始的数据(包括 {{}}),你需要使用 {{% {{x}} %}} ---输出结果:{{x}}

如果想要给模板增加一些注释,请使用 {{! comment }}

声明:
Kissy更多相关链接与帮助请范文本站链接集合
本文文章内容部分摘自 ——玩转KISSY框架.为了查询方便.整理在一起