一个 JS 封装代码的问题

2018-08-29 01:43:31 +08:00
 Mascdo

在写 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"]]]);

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

3507 次点击
所在节点    JavaScript
5 条回复
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
2018-08-29 08:49:50 +08:00
如果我是用户 我希望我要的最终东西就和网上一大堆各种 chart 一样 如果只是到 rect 级别的封装还远远不够
你现在做什么东西
面试题么
Mascdo
2018-08-29 09:16:53 +08:00
@murmur 对啊,面试题。。
dingz
2018-08-29 09:38:32 +08:00
如果一定要按你的思路来可以这样

// 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
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);
}

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/484117

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX