【问题标题】:How to create Ractive's subcomponents dynamically and change them programmatically如何动态创建 Ractive 的子组件并以编程方式更改它们
【发布时间】:2015-09-13 12:50:47
【问题描述】:

我可以使用标签手动实例化(子)组件,但我不知道如何动态地做到这一点,或者,如何使用标签在同一区域插入和删除不同的组件。

今天我以这种方式实例化每个(子)组件:

Ractive.load( '/templates/global/example.html' ).then( function ( Example )
{
       ractive.components.example = new Example( { el : 'aside' } );
});

但是新的(子)组件在 mustache 中看不到它的父实例的数据,只能看到他自己的数据。

【问题讨论】:

  • 为什么要不用标签?
  • 因为我需要能够动态更改附加到元素的组件。我需要以编程方式在同一区域中插入和删除不同的组件。是否可以使用标签来实现这一点?如果可能的话,那就太棒了!
  • 如果有意义,我可以将问题改为如何动态创建子组件并以编程方式更改它们。

标签: components ractivejs


【解决方案1】:

这是一个动态组件:

Ractive.components.dynamic = Ractive.extend({
    template: '<component/>',
    components: {
        component: function() {
            return this.get('name');
        }
    },
    oninit: function(){
        this.observe('name', function(){
            this.reset();
        }, { init: false});
    }
});

只需传入它应该实现的组件的名称:

<dynamic name='{{name}}'/>

在下面查看它的实际操作

Ractive.components.a = Ractive.extend({ template: 'I am A {{foo}}' });
Ractive.components.b = Ractive.extend({ template: 'I am B {{foo}}' });
Ractive.components.c = Ractive.extend({ template: 'I am C {{foo}}' });

Ractive.components.dynamic = Ractive.extend({
    template: '<component/>',
    components: {
        component: function() {
            return this.get('name');
        }
    },
    oninit: function(){
        this.observe('name', function(){
            this.reset();
        }, { init: false});
    }
});


var r = new Ractive({
    el: document.body,
    template: '#template',
    data: {
        foo: 'foo',
        list: ['a', 'b', 'c'],
        name: 'a'
    }
});
<script src="http://cdn.ractivejs.org/latest/ractive.js"></script>
<script id='template' type='text/ractive'>
   
    {{#each list}}
    <input type='radio' name='{{name}}' value='{{.}}'>{{.}}
    {{/each}}
    <br>
    <dynamic name='{{name}}'/>
       
</script>

【讨论】:

  • 你为什么要这样做:this.reset(this.get(''));?似乎是一件很奇怪的事情。提前致谢。
  • @LiorCohen 我认为曾几何时有一个活跃的错误需要这样做。它似乎不再需要了!
  • @martypdx 我再次回到这里只是为了说您的回复是一件艺术品。
  • 谢谢。我也将您的答案扩展到支持数据。 gist.github.com/darylteo/12a5f9bbb63916e10e89ab2bf88d8b5b
【解决方案2】:

想多次支持@martypdx 的回答。受他回答的启发,我想出了一些我想分享的东西。它添加了以下内容:

  1. 创建一个组件类型的多个实例 (Ractive.extend)

  2. 组件实例处于活动状态,并且可以接收来自外部侦听器的消息,即使它们未被渲染。

这是我的小提琴:https://jsfiddle.net/vikikamath/z5otgzpL/9/

// Inspired by http://stackoverflow.com/a/31080919/405117
var mapper = {
	'A': function(instanceId){
  	var handleAData;
  	return Ractive.extend({ 
  			template: 'I am A this is my data: <ul>{{#datas}}<li>{{.}}</li>{{/datas}}</ul>',
        data: {
        	datas:[]
        },
        onrender: function() {
        	handleAData = function(txt){
          	this.push('datas', txt);
          }.bind(this);
          
        	r.on(instanceId, handleAData);
        },
        onunrender: function() {
        	r.off(instanceId, handleAData);
        }
  	});
  }
  ,'B': function(instanceId){
  	var handleBData;
  	return Ractive.extend({ 
  			template: 'I am B this is my data: <ul>{{#datas}}<li>{{.}}</li>{{/datas}}</ul>',
        data: {
        	datas:[]
        },
        onrender: function() {
        	handleBData = function(txt){
          	this.push('datas', txt);
          }.bind(this);
          
        	r.on(instanceId, handleBData);
        },
        onunrender: function() {
        	r.off(instanceId, handleBData);
        }
  	});
  }
  ,'C': function(instanceId){
  	var handleCData;
  	return Ractive.extend({ 
  			template: 'I am C this is my data: <ul>{{#datas}}<li>{{.}}</li>{{/datas}}</ul>',
        data: {
        	datas:[]
        },
        onrender: function() {
        	handleCData = function(txt){
          	this.push('datas', txt);
          }.bind(this);
          
        	r.on(instanceId, handleCData);
        },
        onunrender: function() {
        	r.off(instanceId, handleCData);
        }
  	});
  }
  ,'D': function(instanceId){
  	var handleDData;
  	return Ractive.extend({ 
  			template: 'I am D this is my data: <ul>{{#datas}}<li>{{.}}</li>{{/datas}}</ul>',
        data: {
        	datas:[]
        },
        onrender: function() {
        	handleDData = function(txt){
          	this.push('datas', txt);
          }.bind(this);
          
        	r.on(instanceId, handleDData);
        },
        onunrender: function() {
        	r.off(instanceId, handleDData);
        }
  	});
  }
}

/* arbitrarily select a component */
function pickRandomComponent() {
	return String.fromCharCode(Math.floor(Math.random() * Object.keys(mapper).length) + 65);
}

var DynamicComponent = Ractive.extend({
    template: '<component/>',
    components: {
        component: function() {
            return this.get('name');
        }
    },
    oninit: function(){
        this.observe('name', function(){
            this.reset();
        }, { init: false});
    }
});


var r = new Ractive({
    el: 'main',
    template: '#template',
    components: {
    	dummy: Ractive.extend({ template: 'Welcome message' }),
    	dynamic: DynamicComponent
    },
    data: {
        foo: 'foo',
        list: ['dummy'],
        name: 'dummy',
        textdata: ''
    },
    oninit: function() {
    	this.on("sendDataToCurrentComponent", function() {
      	r.fire(this.get('name'), this.get('textdata'))
      }.bind(this));
      
    	this.on('addComponent', function(){
      	var rndComponent = pickRandomComponent();
        var now = Date.now();
        var componentInstanceName = rndComponent + '-' + now
      	this.components[componentInstanceName] = mapper[rndComponent](componentInstanceName)
      	this.push('list', componentInstanceName);
      }.bind(this));
    }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/ractive/0.7.3/ractive.min.js"></script>
<script id='template' type='text/ractive'>
   	<button on-click="addComponent">Add</button>
 		<div>
   		<input type="text" value="{{textdata}}" placeholder="Send Text to current component" width="900" on-blur="sendDataToCurrentComponent"/>
   	</div>
    {{#each list}}
    <input type='radio' name='{{name}}' value='{{.}}'>{{.}}
    {{/each}}
    <br>
    <dynamic name='{{name}}'/>
       
</script>
<main></main>

【讨论】:

    猜你喜欢
    • 2012-05-01
    • 2015-08-30
    • 1970-01-01
    • 1970-01-01
    • 2017-05-16
    • 2013-09-07
    • 1970-01-01
    • 1970-01-01
    • 2011-07-19
    相关资源
    最近更新 更多