好问题。
如果要向对象添加自定义属性,则这些对象在某种程度上可能是“特殊的”。子类化似乎是一个合理的解决方案。
例如,这是我们将a子类
fabric.Image化为命名图像的方法。这些图像对象然后可能具有“ Gandalf”或“ Samwise”之类的名称。
fabric.NamedImage = fabric.util.createClass(fabric.Image, { type: 'named-image', initialize: function(element, options) { this.callSuper('initialize', element, options); options && this.set('name', options.name); }, toObject: function() { return fabric.util.object.extend(this.callSuper('toObject'), { name: this.name }); }});首先,我们给这些对象一个类型。此类型用于
loadFromJSON自动调用
fabric.<type>.fromObject方法。在这种情况下会是
fabric.NamedImage.fromObject。
然后,我们覆盖
initialize(构造函数)实例方法,以便在初始化对象时也设置“名称”属性(如果提供了该属性)。
然后,我们覆盖
toObject实例方法以在返回的对象中包含“名称”(这是结构中对象序列化的基石)。
最后,我们还需要实现
fabric.NamedImage.fromObject我之前提到的
loadFromJSON方法,以便知道在JSON解析期间要调用的方法:
fabric.NamedImage.fromObject = function(object, callback) { fabric.util.loadImage(object.src, function(img) { callback && callback(new fabric.NamedImage(img, object)); });};我们正在这里加载图像(来自“
object.src”),然后从中创建一个实例
fabric.NamedImage。请注意,到那时,构造函数将已经处理“名称”设置,因为我们之前覆盖了“初始化”方法。
并且我们还需要指定它
fabric.NamedImage是一个异步“类”,这意味着它
fromObject不返回实例,而是将其传递给回调:
fabric.NamedImage.async = true;
现在我们可以尝试一下:
// create image elementvar img = document.createElement('img');img.src = 'https://www.google.com/images/srpr/logo3w.png';// create an instance of named imagevar namedImg = new fabric.NamedImage(img, { name: 'foobar' });// add it to canvascanvas.add(namedImg);// save jsonvar json = JSON.stringify(canvas);// clear canvascanvas.clear();// and load everything from the same jsoncanvas.loadFromJSON(json, function() { // making sure to render canvas at the end canvas.renderAll(); // and checking if object's "name" is preserved console.log(canvas.item(0).name);});


