How to create Ractive's subcomponents dynamically and change them programmatically

前端 未结 2 1182
借酒劲吻你
借酒劲吻你 2021-01-12 22:52

I can instantiate (sub)components manually using tags, but I don\'t know how to do it dynamically, or, how to insert and remove different components in the same area using t

相关标签:
2条回答
  • 2021-01-12 23:25

    Would like to upvote @martypdx's answer more than once. Inspired by his answer, I came up with something I'd like to share. It adds the following things:

    1. Create multiple instances of a type of Component (Ractive.extend)

    2. Component instances are alive and can receive messages from external listeners even if they have been unrendered.

    Here is my fiddle: 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>

    0 讨论(0)
  • 2021-01-12 23:45

    Here's a dynamic component:

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

    Just pass in the name of the component it should implement:

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

    See it in action below

    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>

    0 讨论(0)
提交回复
热议问题