V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐关注
Meteor
JSLint - a JavaScript code quality tool
jsFiddle
D3.js
WebStorm
推荐书目
JavaScript 权威指南第 5 版
Closure: The Definitive Guide
Mascdo
V2EX  ›  JavaScript

一个 JS 封装代码的问题

  •  
  •   Mascdo · 2018-08-29 01:43:31 +08:00 · 3507 次点击
    这是一个创建于 2311 天前的主题,其中的信息可能已经有所发展或是发生改变。

    在写 d3 的相关内容,不过我 JS 掌握不是很多。 题目要求组块化,我就想把画矩形的函数给封装起来,当做一个方法,以后画矩形的话只要调用一下就行了。以前学过一些 sql,考虑用 sql 的方式拼装,结果好像不太行,不知道有谁能指导一下怎么做么,或者有什么好的方法。

    这里是原来我写的代码

    	var rect = svg.selectAll("rect")
             .data(dataset)  // 绑定数据
              .enter()        // 获取 enter
              .append("rect") // 添加 rect 元素,绑定和数组长度一致
              .attr("fill", "steelblue") // 设置填充颜色
              .attr("x", function(d, i){ // x
                return padding.left + i * rectStep;
              })
              .attr("y", function(d){ //y
                return height - padding.bottom - d;
              })
              .attr("width", rectWidth) // 设置矩形的高度
              .attr("height", function(d){
                return d;
              })
    

    这里开始是我封装的代码,但是封装的方式不对,我是想把自己固定想要传的参数写清楚,其他不固定的参数,就放在一个数组里传进来,最后的参数[["attr",["fill", "blue"]],["attr",["fill","pink"]] 放进来以后,可以在 svg 最后执行的位置,执行 .attr("fill", "blue").attr("fill", "pink") 如果是其他的方法当然执行的不同,不过自己试了一下,根本行不通啊!!!原来的代码不难,就是封装没思路,请指教一下谢谢!

    另外补充一点,我知道可以 attr({key1: value1}, {key2, value2})的方式设置多个属性,但是这种方法的思路有局限性,就比如说要给它添加一个 mouseover 事件,没办法添加,类似这里结尾

      svg.selectAll(".bar")
      .data(data)
      .enter().append("rect")
      .attr("class", "bar")
      .attr("x", function(d) { return x(d.city); })
      .attr("width", x.rangeBand())
      .attr("y", function(d) { return y(d.money); })
      .attr("height", function(d) { return height - y(d.money); })
      .on('mouseover', tip.show)
      .on('mouseout', tip.hide)
    

    封装代码:

    function Rect(svg, data, width, height, x, y, argsarray ){
     var length = argsarray.length;
       var co ='';
     for (var i = 0; i < argsarray.length; i++) {
       co += '.' +argsarray[i][0] + '("' + argsarray[i][1][0] + '","' +argsarray[i][1][1] +'")';
      console.log(co);
     // 这里输出 .attr("fill","blue").attr("fill","pink") 
     }
      svg.selectAll("rect")
                   .data(data)  // 绑定数据
                   .enter()        // 获取 enter
                .append("rect") // 添加 rect 元素,绑定和数组长度一致
                .attr("x", x)
                .attr("y", y)
                .attr("width", width) // 设置矩形的高度
                .attr("height", height)
                //.(eval(co));
    }
    var getRectx = function(d, i){ return padding.left + i * rectStep};
    var getRecty = function(d){ return height - padding.bottom - d};
    var getHeight = function(d){ return d};
    
    Rect(svg, dataset, rectWidth, getHeight, getRectx, getRecty, [["attr",["fill", "blue"]],["attr",["fill","pink"]]]);
    

    这里设置成蓝色又设置成粉色就是看看数组中多属性能不能使用。

    5 条回复    2018-08-29 09:39:14 +08:00
    dingz
        1
    dingz  
       2018-08-29 08:45:41 +08:00
    先把你的默认参数都封装到一个对象里, 就比如叫作 defaultOptions 吧,放到全局变量。
    然后这个函数接受一个新的 options 对象作为参数, 函数里把 options 继承 defaultOptions。
    然后函数后续就对这个参数对象要干嘛干嘛的用即可。

    .attr("fill", options.fill)
    .attr("x", options.x)
    .attr("y", options.y)
    .attr("width", options.width) // 设置矩形的高度
    .attr("height", options.height)
    murmur
        2
    murmur  
       2018-08-29 08:49:50 +08:00
    如果我是用户 我希望我要的最终东西就和网上一大堆各种 chart 一样 如果只是到 rect 级别的封装还远远不够
    你现在做什么东西
    面试题么
    Mascdo
        3
    Mascdo  
    OP
       2018-08-29 09:16:53 +08:00
    @murmur 对啊,面试题。。
    dingz
        4
    dingz  
       2018-08-29 09:38:32 +08:00   ❤️ 1
    如果一定要按你的思路来可以这样

    // argsObj 是个对象,他的属性对应 attr 或者 on,
    //其下的属性也是个对象对应属性名或事件,
    //最终叶子属性可以是数组或者不是
    var argsObj = {
    attr: {
    fill: ['red', 'blue'],
    height: 1213
    },
    on: {
    mouseover: tip.show,
    mouseout: tip.hide
    }
    };

    function Rect(svg, data, width, height, x, y, argsObj ){
    for (var i in argsObj) {
    if (argsObj[i] && typeof argsObj[i] === 'object') {
    for (var j in argsObj[i]) {
    if (Array.isArray(argsObj[i][j]))
    for (var k = 0; k < argsObj[i][j].length; k++)
    svg[i](j, argsObj[i][j][k]);
    else
    svg[i](j, argsObj[i][j]);
    }
    }
    }
    }
    dingz
        5
    dingz  
       2018-08-29 09:39:14 +08:00
    或者把不固定参数交给一个回调函数做
    function afterDraw(svg)
    {
    svg.attr("fill", "steelblue").attr("fill", "red").on('mouseover', tip.show);
    }

    function Rect(svg, data, width, height, x, y, afterDraw)
    {
    ......
    if (afterDraw) afterDraw(svg);
    }
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2999 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 28ms · UTC 14:36 · PVG 22:36 · LAX 06:36 · JFK 09:36
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.