VueJS - Função Render

Vimos os componentes e o uso deles. Por exemplo, temos um conteúdo que precisa ser reutilizado em todo o projeto. Podemos converter o mesmo como um componente e usá-lo.

Vamos dar uma olhada em um exemplo de um componente simples e ver o que a função de renderização tem que fazer dentro dele.

Exemplo

<html>
   <head>
      <title>VueJs Instance</title>
      <script type = "text/javascript" src = "js/vue.js"></script>
   </head>
   <body>
      <div id = "component_test">
         <testcomponent></testcomponent>
      </div>
      <script type = "text/javascript">
         Vue.component('testcomponent',{
            template : '<h1>Hello World</h1>',
            data: function() {
            },
            methods:{
            }
         });
         var vm = new Vue({
            el: '#component_test'
         });
      </script>
   </body>
</html>

Considere o exemplo acima de um componente simples que imprime Hello World conforme mostrado na captura de tela a seguir.

Agora, se quisermos reutilizar o componente, podemos fazê-lo apenas imprimindo-o novamente. Por exemplo,

<div id = "component_test">
   <testcomponent></testcomponent>
   <testcomponent></testcomponent>
   <testcomponent></testcomponent>
   <testcomponent></testcomponent>
</div>

E a saída será a seguinte.

No entanto, agora precisamos de algumas alterações no componente. Não queremos que o mesmo texto seja impresso. Como podemos mudar isso? Caso digamos algo dentro do componente, isso será levado em consideração?

Vamos considerar o seguinte exemplo e ver o que acontece.

<div id = "component_test">
   <testcomponent>Hello Jai</testcomponent>
   <testcomponent>Hello Roy</testcomponent>
   <testcomponent>Hello Ria</testcomponent>
   <testcomponent>Hello Ben</testcomponent>
</div>

O resultado permanece o mesmo que vimos anteriormente. Não altera o texto como desejamos.

O componente fornece algo chamado de slots. Vamos aproveitar e ver se obtemos os resultados desejados.

Exemplo

<html>
   <head>
      <title>VueJs Instance</title>
      <script type = "text/javascript" src = "js/vue.js"></script>
   </head>
   <body>
      <div id = "component_test">
         <testcomponent>Hello Jai</testcomponent>
         <testcomponent>Hello Roy</testcomponent>
         <testcomponent>Hello Ria</testcomponent>
         <testcomponent>Hello Ben</testcomponent>
      </div>
      <script type = "text/javascript">
         Vue.component('testcomponent',{
            template : '<h1><slot></slot></h1>',
            data: function() {
            },
            methods:{
            }
         });
         var vm = new Vue({
            el: '#component_test'
         });
      </script>
   </body>
</html>

Como visto no código acima, no modelo adicionamos slot, portanto, agora leva o valor para enviar dentro do componente, conforme mostrado na imagem a seguir.

Agora, vamos considerar que queremos mudar a cor e o tamanho. Por exemplo, atualmente estamos usando a tag h1 e queremos alterar a tag HTML para tag p ou tag div para o mesmo componente. Como podemos ter flexibilidade para realizar tantas mudanças?

Podemos fazer isso com a ajuda da função render. A função Render ajuda a tornar o componente dinâmico e a usar da maneira necessária, mantendo-a comum e ajudando a passar argumentos usando o mesmo componente.

Exemplo

<html>
   <head>
      <title>VueJs Instance</title>
      <script type = "text/javascript" src = "js/vue.js"></script>
   </head>
   <body>
      <div id = "component_test">
         <testcomponent :elementtype = "'div,red,25,div1'">Hello Jai</testcomponent>
         <testcomponent :elementtype = "'h3,green,25,h3tag'">Hello Roy</testcomponent>
         <testcomponent :elementtype = "'p,blue,25,ptag'">Hello Ria</testcomponent>
         <testcomponent :elementtype = "'div,green,25,divtag'">Hello Ben</testcomponent>
      </div>
      <script type = "text/javascript">
         Vue.component('testcomponent',{
            render :function(createElement){
               var a = this.elementtype.split(",");
               return createElement(a[0],{
                  attrs:{
                     id:a[3],
                     style:"color:"+a[1]+";font-size:"+a[2]+";"
                  }
               },
               this.$slots.default
               )
            },
            props:{
               elementtype:{
                  attributes:String,
                  required:true
               }
            }
         });
         var vm = new Vue({
            el: '#component_test'
         });
      </script>
   </body>
</html>

No código acima, mudamos o componente e adicionamos a função render com a propriedade props usando o seguinte trecho de código.

Vue.component('testcomponent',{
   render :function(createElement){
      var a = this.elementtype.split(",");
      return createElement(a[0],{
         attrs:{
            id:a[3],
            style:"color:"+a[1]+";font-size:"+a[2]+";"
         }
      },
      this.$slots.default
      )
   },
   props:{
      elementtype:{
         attributes:String,
         required:true
      }
   }
});

Os adereços se parecem com o seguinte.

props:{
   elementtype:{
      attributes:String,
      required:true
   }
}

Definimos uma propriedade chamada elementtype, que leva os atributos de campo do tipo string. Outro campo obrigatório, que menciona que o campo é obrigatório.

Na função de renderização, usamos a propriedade elementtype conforme visto no código a seguir.

render :function(createElement){
   var a = this.elementtype.split(",");
   return createElement(a[0],{
      attrs:{
         id:a[3],
         style:"color:"+a[1]+";font-size:"+a[2]+";"
      }
   },
   this.$slots.default
   )
}

A função Render leva createElement como argumento e retorna o mesmo. CreateElement cria o elemento DOM da mesma maneira que em JavaScript. Também dividimos o elementtype por vírgula, usando os valores do campo attrs.

CreateElement está usando o primeiro parâmetro como o elementtag a ser criado. Ele é passado para o componente usando o seguinte trecho de código.

<testcomponent  :elementtype = "'div,red,25,div1'">Hello Jai</testcomponent>

O componente precisa ocupar o campo de adereços conforme mostrado acima. Ele começa com: e o nome dos adereços. Aqui, estamos passando a tag do elemento, a cor, o tamanho da fonte e o id do elemento.

Na função render, em createElement, estamos dividindo por vírgula, então o primeiro elemento é o elementtag, que é dado ao createElemet conforme mostrado no seguinte trecho de código.

return createElement(
   a[0],{
      attrs:{
         id:a[3],
         style:"color:"+a[1]+";font-size:"+a[2]+";"
      }
   },
   this.$slots.default
)

a[0]é a tag do elemento html. O próximo parâmetro são os atributos da tag do elemento. Eles são definidos no campo attr no seguinte trecho de código.

attrs:{
   id:a[3],
   style:"color:"+a[1]+";font-size:"+a[2]+";"
}

Definimos dois atributos para a tag do elemento - id e style. Para id, estamos passando a [3], que é o valor que temos após a divisão por vírgula. Usando o estilo, definimos a cor e o tamanho da fonte.

O último é o slot, que é a mensagem que demos no componente no seguinte trecho de código.

<testcomponent :elementtype = "'div,red,25,div1'">Hello Jai</testcomponent>

Definimos o texto a ser impresso no createElement usando o seguinte trecho de código.

this.$slots.default

Ele assume o padrão atribuído no campo do componente.

A seguir está a saída que obtemos no navegador.

Os elementos também mostram a estrutura. Estes são os componentes que definimos -

<div id = "component_test">
   <testcomponent :elementtype = "'div,red,25,div1'">Hello Jai</testcomponent>
   <testcomponent :elementtype = "'h3,green,25,h3tag'">Hello Roy</testcomponent>
   <testcomponent :elementtype = "'p,blue,25,ptag'">Hello Ria</testcomponent>
   <testcomponent :elementtype = "'div,green,25,divtag'">Hello Ben</testcomponent>
</div>