// Basic usage of mixins
const empty_mixin = {
  filters: {empty: value= > {
        value || The '-'}},created() {
    console.log('injection created'); }}new Vue({
  el: document.querySelector('#app'),
  mixins: [empty_mixin],
  data: {user: ' '
  },
  template: `<h1>hello, {{ user | empty }}</h1>`
})
Copy the code

Functions: 1. The same logic of multiple components can be extracted. Disadvantages: 1

In some cases, utils can be used to solve the problem. Vue just provides a loophole for developers to use. In simple components, you can use mixins to avoid CV code.

Implement a page exit hook function based on the merge strategy in VUE.

const originalOptionMergeStrategies = Vue.config.optionMergeStrategies
originalOptionMergeStrategies.exit = originalOptionMergeStrategies.created

const notify = (name, vm) = > {
  let lifeCycle = vm.$options[name]
  if(lifeCycle && lifeCycle.length) {
    lifeCycle.forEach(lc= >lc.call(vm))
  }

  const children = vm.$children
  if(children && children.length) {
    children.forEach(child= > notify(name, child))
  }
}

const bind = vm= > {
  window.addEventListener('visibilitychange'.() = > {
    if(document.visibilityState === 'hidden') {
      notify('exit', vm)
    }
  })
}

const vm = new Vue({
  el: document.querySelector('#app'),
  template: `<div>hello</div>`.exit() {
    alert('leave the current page? ')
  }
})

bind(vm)
Copy the code

Simple application of the plug-in mechanism in VUE

const logger = {
  // Plug-ins in vue require an install method. The install method takes two arguments
  install(Vue, options) {
    Object.defineProperty(Vue.prototype, '$log', {
      value:() = > console.log('printed log ~'),
      configurable:false.enumerable:false.writable: false
    })
  }
}

Vue.use(logger)

new Vue({
  el: document.querySelector('#app'),
  template:`<h1>hello world</h1>`.created() {
    this.$log()
  }
})
Copy the code

This plugin mechanism is used quite a bit in Vue. Developers can take advantage of this by developing their own set of components based on their current development project and then using them directly after use in the project, rather than importing them every time they are used.

const Button = {
  name: 'el-button'.template:`<button @click='onClick'>{{ label }}</button>`.props: {label: {
      default: 'button'}},methods: {onClick() {
      this.$emit('click')}}}const PUI = [
  Button
]


PUI.install = (Vue, options) = > {
  PUI.forEach(({ name, ... component }) = > {
    Vue.component(name, component)
  })
}

Vue.use(PUI)

new Vue({
  el: document.querySelector('#app'),
  template: `
      

hello

`
.methods: {handleClick() { console.log('Click is valid ~'); }}})Copy the code

In fact, it is already mentioned on the vUE website

The following components are based on the following business scenarios: Currently, the company needs to develop a new project, which will use the components in the original project. However, the problem is that the original project is written based on the React framework, and now the React component needs to be used in the VUE project. The React component will still use reactdom. render, and the rendered component will be placed in a new DOM structure. When using the React component, the react component will be transparent to the properties of the Vue component. In the React component, children may be a Vue component, so we also need to implement rendering a Vue component in the React componentCopy the code

// React mounts the vue component
class VueWrapper extends React.Component {
  constructor(props){
    super(props)
  }

  componentWillUnmount() {
    this.vueInstance.$destroy()
  }

  createVueInstance = el= > {
    const{ component, on, ... props } =this.props

    this.vueInstance = new Vue({
      el,
      data: props,
      render(h) {
        return h('xxx-internal-component', {props: this.$data, on},
          [
            h('yyy-internal-react-wrapper', { props: {
              component: () = > React.createElement('div', {}, this.children)
            }})
          ]
        )
      },
      components: {
        'xxx-internal-component': component,
        'yyy-internal-react-wrapper': ReactWrapper
      }
    })

  }

  render() {
    return React.createElement('div', { ref: this.createVueInstance })
  }
}

const makeReactComponent = Component= > {
  return class ReactRunInVue extends React.Component {
    static displayName = 'vue-react'
    constructor(props) {
      super(props)
      this.state = { ... props } }wrappChildren(children) {
      return {
        render : h= > h('div', children)
      }
    }

    render() {
      const{ children, ... rest } =this.state
      const wrappedChildren = this.wrappChildren(children)
      returnReact.createElement( Component, { ... rest }, children && React.createElement(VueWrapper, {component: wrappedChildren })

      )
    }
  }
}

// reactWrapper component, vue component
/ / nature

const ReactWrapper = {
  props: ['component'].render(h){
    return h('div', { ref: 'react'})},methods: {
    // Render the React component to the div core: The react core to run inside the vue is to render to a div
    mountReactComponent(component) {
      const Component = makeReactComponent(component)
      // React to children
      const children = this.$slots.default ! = =void 0 ? { children: this.$slots.default } : {} ReactDOM.render( React.createElement( Component, { ... this.$attrs, ... this.$listeners, ... children,ref: ref= > (this.reactComponentRef = ref) }
        ),
        this.$refs.react
      )
    },

    mounted() {
      this.mountReactComponent(this.$props.component)
    },

    beforeDestroy() {
      ReactDOM.unmountComponentAtNode(this.$refs.react)
    },

    inheritAttrs: false.watch: {
      $attrs: {
        deep: true.handler() {
          this.reactComponentRef.setState({... this.$attrs}) } },'$props.component': {
        handler(newComponent) {
          this.mountReactComponent(newComponent)
        }
      }
      // ...}}}// Check whether it is the React component
const isReactComponent = component= > {
  return! (typeof component === 'function' && 
    component.prototype &&
    (
      (component.prototype.constructor.super && component.prototype.constructor.super.isVue) ||
      component.prototype instanceof Vue
    )
  )
}

// React components are converted to vue components
// Input is a React component and output is a vue component
const resolver = (component) = > {
  return {
    components: {
      ReactWrapper // It's all done in this component
    },
    props: [].inheritAttrs: false.render(h) {
      return h ('react-wrapper', 
       { 
        props: { component },
        attrs: this.$attrs,
        on: this.$listeners
       }),
       this.$slots.default
    }
  }
}


const ReactRunInVuePlugin = {
  install(Vue, options) {
    // Keep the original Components merge strategy
    const originalComponentOptionMergeStrategies = Vue.config.optionMergeStrategies.components

    Vue.config.optionMergeStrategies.components = (parent, ... args) = > {
      constmergedComponentOptions = originalComponentOptionMergeStrategies(parent, ... args)const wrappedComponents = mergedComponentOptions 
        // Iterate over the object
        ? Object.entries(mergedComponentOptions).reduce((acc, [k, v]) = > ({
          ...acc,
          [k] : isReactComponent(v) ? resolver(v) : v
        }), {})
        : mergedComponentOptions

      // Mixin the object
      return Object.assign(mergedComponentOptions, wrappedComponents)
    }

    Vue.prototype.constructor.isVue = true}}// Use react plugin in vue
class Button extends React.Component {
  render() {
    return React.createElement('div', {}, [
      React.createElement('h2', {}, 
        React.createElement('em', {}, this.props.children)
      )
    ])
  }
}

Vue.use(ReactRunInVuePlugin)

new Vue({
  el: document.querySelector('#app'),
  components: { 'el-button': Button },
  template: '
      

Use react component in vue

click me
'
,})Copy the code

When registering components globally in a Vue project, do you import them one by one? A trick to teach you no longer need to import a number of components, the use of vUE plugin mechanism, Vue to expose the plugin to us this hole, as for how to use, that is the eight impostors cross the Sea each show their powers

const requireComponent = require.context('/'.true./\.vue$/);

const install = (Vue) = > {
	
    requireComponent.keys().forEach((fileName) = > {

        let config = requireComponent(fileName);

        let componentName = parseVarNameByFilePath(fileName);

        Vue.component(componentName, config.default || config);
    });
};
Copy the code