This is the 20th day of my participation in the Genwen Challenge

The set-top box of Party A is huawei (Jukpit), many permissions cannot be obtained, and key conflicts are common. The question today is that the keys of TV terminal and mobile terminal are limited. How to customize the Window method in the project and pass it to the back end to call

preface

JavaScript window object

All browsers support the Window object. All JavaScript global objects, functions, and variables automatically become members of the Window object. You can use properties and methods of the window object anywhere. The common methods of navigator and Screen are: Window.open (), window.close(), window.moveto (), window.resizeto (), alert(), confirm(), prompt() commonly used properties are: Var w = window. InnerWidt | | document. The documentElement. ClientWidth | | document. Body. ClientWidth (the chestnuts representative)

Custom window methods

The existing Window method is used or not sufficient for a function (like I’m doing now), so you need to customize the Window method in React or Vue to make it easier for the back end to call.

/ / way
window.functionA = () = > {}
window.functionB = () = > {}
window.functionC = () = > {}

// Use JQuery
$.extend(window, {
    A:function(){},
    B:function(){},
    C:function(){},})3 / / way
(() = > {
   var defining = {
      A: function() {},B: function() {},C: function() {}};Object.keys(defining).forEach(key= > {
    window[key] = defining[key]; }); }) ();// Method 4 (the variable under the window object is an object)
window[variable] =function(){}
Copy the code

Note: some students said that method definition failed, maybe you didn’t use the arrow function, so don’t forget let _this = this

Vue custom window methods

The following methods are not written in the global app.vue, but in the component. The advantage is that the vue methods cannot be executed in third-party components because of the scope involved and the asynchronous execution of property functions within the component. Or there is a problem with the order of execution when it is executed externally (the intention is to execute my function after the third party component function has finished executing).

methods:{
  // Create the phone component
  createCallComponent(phoneNum) {
    if (window.callComp && !window.callComp.isDestroyed) {
      return;
    };
    window.callComp = new UdeskCallcenterComponent({
       container: document.body,
       token: this.agentToken,
       subDomain: this.subDomain,
       showManualScreenPop: false.onHangup: function(conversation) { // Execute when the phone hangs up
         getCallId(conversation.call_id);  // Call the bound method here and call callid
         window.callComp.destroy(); // Destroy the phone component
         window.callComp = null; // Destroy the phone component}}); },// Get the current CALlid each time the call ends, and save the obtained value to the background interface
  callIdFun(val) {
    this.call_id = val;
    console.log(this.call_id); . }},mounted() {
  // Bind the vue component's methods to the window
  window['getCallId'] = val= > {
    this.callIdFun(val)
  }
}
Copy the code

In the process of mixed development, H5 can call the internal methods of the client (ios, Android) through the jsBridge method. Similarly, the client also needs to be able to call the JS methods defined in the H5 page. However, in VUE, all methods are declared inside the component and can only be called inside the component. Instead of binding the Window object, you can expose the methods defined in the VUE component to the Window object using the following methods.

created(){},mounted() {
    // Bind the backToday method under the window to make it available to external calls
     window['backToday'] = () = > {
        this.KeyBack()
     }
 },
 methods: {
    KeyBack() {
        // to do something}}// Let _this = this
Copy the code

In the process of mixed development, how does vue’s custom window method communicate with the native one? Since Android cannot directly call the methods of each Vue object, it can only call the function below window, so we need a model: The message is first sent to function under the window, which calls the parent component’s code through function under the window, and the parent component calls the child component’s code. Vue code: directly create a project using Vue CLI, and change host from localhost to PC’s local Ip in config/index.js to facilitate debugging on mobile phones. Here’s an example:

// Create a child of childComponent. vue where the receiveMsgFromParent(MSG) function is defined<template>
  <div id="childComponent" style="background-color: #42b983">
    <div>{{childMsg}}</div>
    <br/>
    <button @click="toSecondComponent">Go to the second screen</button>
  </div>
</template>
Copy the code
<script>
  export default {
    name: 'childComponent'.data: function () {
      return {
        childMsg: "This is child component"}},methods: {
      receiveMsgFromParent: function (msg) {
        alert("" + msg);
        this.childMsg = "receive msg = " + msg;
      },
      toSecondComponent: function () {
        this.$router.replace({path: "/SecondComponent"}); }},created() {
      this.$parent.setComponent(this);
    }
  }
</script>
Copy the code

Define a function under window in app. vue that lets the Android WebView find the method

// Also define a setComponent(Component) method in app.vue
var curComponent;
export default {
    name: 'App'.components: {
        ChildComponent,
    },
        data: function() {
            return {
            richtext: 'App.vue receive msg'}; },methods: {
            setComponent: function(component) { curComponent = component; }},created() {
            this.$router.push({ path: 'ChildComponent'}); }};window['receiveMsgFromNative'] = function(msg) {
    curComponent.receiveMsgFromParent(msg);
};
Copy the code

This.$parent. SetComponent (this); app.vue; Method, so that the message is correctly received and delivered to the vUE component at the top of the route.

The android part

Android this piece, according to the user feedback, it is suggested to use QQ X5 browser to load, his crash rate is relatively low. Note that if you want to pass data of type Stirng to Js, you need to enclose the data in quotes.

digression

If we forget the TV side window function, we usually write global methods, what are the ways?

// Write directly in main.js
Vue.prototype.changeData = function (){ //changeData is a custom function name
  console.log('222');
}
// Run the function directly within the component through this

// Create a global.js file and reference main.js (recommended)
exports.install = function (Vue, options) {
   Vue.prototype.text1 = function (){// global function 1
    console.log('Global function 1');
    };
    Vue.prototype.text2 = function (){// global function 2
    console.log('Global function 2');
    };
};
// Vue.use(global); // Register the global function as a plug-in and still use this within the component
Copy the code

React Custom window methods

ReactNative, for example

React Native specifies the page physical return listener. I haven’t seen RN’s project yet. Note: Return true in the onBackAndroid callback function is essential.

componentWillMount(){
        BackHandler.addEventListener('hardwareBackPress'.this.onBackAndroid);
}
componentWillUnmount() {
    BackHandler.removeEventListener('hardwareBackPress'.this.onBackAndroid);
}
onBackAndroid = () = > {
    if (this.lastBackPressed && this.lastBackPressed + 2000> =Date.now()) {
    // Press the back key within the last 2 seconds to exit the application.
        BackHandler.exitApp();
          return;
        }
        this.lastBackPressed = Date.now();
        ToastAndroid.show('Press exit app again',ToastAndroid.SHORT);
        return true;
    };
onBackAndroid = () = > {
    if (this.lastBackPressed && this.lastBackPressed + 2000> =Date.now()) {
       // Press the back key within the last 2 seconds to exit the application.
        BackHandler.exitApp();
        return;
    }
        this.lastBackPressed = Date.now();
        ToastAndroid.show('Press exit app again',ToastAndroid.SHORT);
        return true;
};
Copy the code

Native JS listens to the phone’s physical back key

JavaScript does not have an API to listen for physical return keys, so you can only use popState event listening.

pushHistory(); 
   window.addEventListener("popstate".function(e) { 
     window.location = 'http://www.baidu.com';
   }, false); 
   function pushHistory() { 
     var state = { 
       title: "title".url: "#"
     }; 
     window.history.pushState(state, "title"."#"); } This function is declared in xback.js and must be declared again in app.js, otherwise the listener will fail to return the event.Xback.listen (function(){alert('oh! you press the back button'); }); * /; !function(pkg, undefined){
  var STATE = 'x-back';
  var element;
  var onPopState = function(event){
    event.state === STATE && fire();
  }
  var record = function(state){
    history.pushState(state, null, location.href);
  }
  var fire = function(){
    var event = document.createEvent('Events');
    event.initEvent(STATE, false.false);
    element.dispatchEvent(event);
  }
  var listen = function(listener){
    element.addEventListener(STATE, listener, false);
  }
  ;!function(){
    element = document.createElement('span');
    window.addEventListener('popstate', onPopState);
    this.listen = listen;
    record(STATE);
  }.call(window[pkg] = window[pkg] || {}); } ('XBack');
// Call mode

XBack.listen(function(){
  alert('back');
});
Copy the code

The resources

JsBridge document