How to access functions defined in js file inside

2019-06-11 09:03发布

问题:

I have created a function in global.function.js file as

function getData(flag) {
if (flag === 1) {
  return "one";
 } 
else {
  return "not one";
 }
}

which then is imported using custom-js-import.html element:

<script src="global.function.js"></script>

When I tried to access the above function in custom-element.html, I am able to access it in the script part but not in the template part. Is there any way I can access the function inside the HTML element?

<!-- custom-element.html -->
<link rel="import"  href="https://polygit.org/components/polymer/polymer-element.html">
<link rel="import" href="custom-js-import.html">

<dom-module id="custom-element">

  <template>
    <div>
      Hello
    </div>
    <div id="data"></div>
    <div>{{getData(1)}}</div><!-- Unable to access this from here -->
    <div>{{getLocalData()}}</div>
  </template>

<script>
  // Define the class for a new element called custom-element
  class CustomElement extends Polymer.Element {
    static get is() { return "custom-element"; }
    constructor() {
        super();
      }

      ready(){
        super.ready();
        this.$.data.textContent = "I'm a custom-element.";
        console.log(getData(1));//can be easily accessed from here
      }

      getLocalData(){
        return "local";
      }

  }
  // Register the new element with the browser
  customElements.define(CustomElement.is, CustomElement);
</script>
</dom-module>

Sample Code

回答1:

Is there any way I can access the function inside the HTML element?

Not really. In order to use data in a template you need to bind it to a property (Polymer calls this data binding).

Polymer's data binding system is designed for binding values to a template. Those values are typically just literals (e.g. strings and numbers) or plain ole javascript objects e.g. {a: 'someval', b: 5}. Polymer's data binding system is not designed to bind functions to a template and you can't just use javascript inside of a template. (If you're really into that idea, check out React as a replacement to polymer).

The polymer way to do what you're trying to do is to use a computed property. Instead of calling a function inside the template, create a computed property that reacts to changes of other variables. When the state of a property changes, the computed property will change too. This state can be thought of as the argument of your function.

I think it's better just to see the code working yeah (tested in chrome)?

<link rel="import" href="https://polygit.org/components/polymer/polymer-element.html">
<link rel="import" href="custom-js-import.html">

<dom-module id="custom-element">

  <template>
    <div>
      Hello
    </div>
    <label>
      <input type="number" value="{{flag::input}}">
    </label>
    <h1>from flag: [[flag]]</h1>
    <div id="data"></div>
    <div>{{boundComputedData}}</div><!-- Unable to access this from here -->
    <div>{{getLocalData()}}</div>
  </template>

  <script>
    // Define the class for a new element called custom-element
    class CustomElement extends Polymer.Element {
      static get is() {
        return "custom-element";
      }
      constructor() {
        super();
      }

      getData(flag) {
        const flagAsNumber = parseInt(flag);
        if (flagAsNumber === 1) {
          return "one";
        } else {
          return "not one";
        }
      }

      ready() {
        super.ready();
        this.$.data.textContent = "I'm a custom-element.";
        console.log(this.getData(1)); //can be easily accessed from here
      }

      getLocalData() {
        return "local";
      }



      static get properties() {
        return {
          flag: {
            type: Number,
            value: 0
          },
          boundComputedData: {
            type: String,
            computed: 'getData(flag)'
          }
        };
      }

    }
    // Register the new element with the browser
    customElements.define(CustomElement.is, CustomElement);
  </script>
</dom-module>

<custom-element></custom-element>

So What I'm doing here is:

creating a computed property boundComputedData and setting the computed property to 'getData(flag)' which will make it use the class function getData.

Now whenever the state the property flag changes, the computed property will update.

Hope it helps!



回答2:

Thanks to Rico Kahler for suggesting me to use a mixin. Using mixin solved my problem. You can view the full working sample here.

All the global functions can be defined in the mixin.

<!--custom-mixin.html-->
<script>
  const CustomMixin = superclass => class extends superclass {

static get properties() {
  return {};
}

connectedCallback() {
  super.connectedCallback();
}

getData(flag) {
   if (flag === 1) {
    return "one(From Mixin)";
   } else {
    return "not one(From Mixin)";
   }
  }
 };
</script>

And remember to import the mixin file and add that mixin to your element.

<!-- custom-element.html -->
<link rel="import" href="https://polygit.org/components/polymer/polymer-element.html">
<link rel="import" href="custom-mixin.html">

<dom-module id="custom-element">

  <template>
    <div>
      Hello
    </div>
    <div id="data"></div>
    <div>{{getData(1)}}</div>
    <!-- Unable to access this from here -->
    <div>{{getLocalData()}}</div>
  </template>

  <script>
    // Define the class for a new element called custom-element
    class CustomElement extends CustomMixin(Polymer.Element) {
        static get is() {
          return "custom-element";
        }
        constructor() {
          super();
        }

        ready() {
          super.ready();
          this.$.data.textContent = "I'm a custom-element.";
          console.log(getData(1)); //can be easily accessed from here
        }

        getLocalData() {
          return "local";
        }

      }
      // Register the new element with the browser
    customElements.define(CustomElement.is, CustomElement);
  </script>
</dom-module>