vue use tips

1, multi-chart resize event to the center

1.1 General situation

 

Sometimes we encounter such a scenario, there are several components of a chart in the browser when we want to resize the chart also resize, so we will write in the parent container assembly:

 

mounted() {

  setTimeout(() => window.onresize = () => {

    this.$refs.chart1.chartWrapperDom.resize()

    this.$refs.chart2.chartWrapperDom.resize()

    // ...

  }, 200)

destroyed() { window.onresize = null }

 

If you like this chart component with parent container components are not in a page, subassemblies status was put parent component management, in order to facilitate maintenance, we naturally want the event and state subcomponents maintained by yourself, so add remove components when you do not need to modify one by one parent component

 

1.2 Optimization

 

This uses lodash throttle throttle function, you can also achieve their own, this article also throttling of reference. In Echarts an example, the graph in each component:

 

computed: {

  /**

   * Charts DOM

   */

  chartWrapperDom() {

    const dom = document.getElementById('consume-analy-chart-wrapper')

    return dom && Echarts.init(dom)

  },

  /**

   * Charts resize throttle, used here lodash, you can also use your own setTimout throttling

   */

  chartResize() {

    return _.throttle(() => this.chartWrapperDom && this.chartWrapperDom.resize(), 400)

  }

},

mounted() {

  window.addEventListener('resize', this.chartResize)

},

destroyed() {

  window.removeEventListener('resize', this.chartResize)

}

 

1.3 Optimization again

 

Here because multiple chart instances use the same set of initialization logic, you can use extends to consider reuse, so I think Mixins Vue offers, so here I made a point of optimization, you can make the same type of chart components each more elegant point: a new mixin.js file:

 

import Echarts from 'echarts'

import _ from 'lodash'

export default {

  computed: {

    / * Charts DOM * /

    $_chartMixin_chartWrapperDom() {

      const dom = document.getElementById(this.thisDomId)

      return dom && Echarts.init(dom)

    },

    

    / ** charts resize throttle, used here lodash, you can also use your own setTimout throttling * /

    $_chartMixin_chartResize() {

      return _.throttle(() => this.$_chartMixin_chartWrapperDom.resize(), 400)

    }

  },

  methods: {

    / * Initialize chart * /

    $ _ChartMixin_initChart () {

      this.$_chartMixin_chartWrapperDom.setOption({ /* options */ }

  },

  

  mounted() {

    this.$_chartMixin_initChart()

    window.addEventListener('resize', this.$_chartMixin_chartResize)

  },

  destroyed() {

    window.removeEventListener('resize', this.$_chartMixin_chartResize)

  }

}

 

Then in each chart components:

 

 

<script type='text/javascript'>

import ChartMixin from './mixin'

export default {

  mixins: [ChartMixin],

  data() {

    return {

      thisDomId: 'consume-analy-chart-wrapper'

    }

  }

}

</script>

 

This graph may be incorporated in each assembly prior to resize event logic mixin.js defined, and the automatic initialization and self-destruct when the event is destroyed -

 

 

2, global filters registration

 

2.1 General situation

 

Official registration filter method:

 

export default {

  data () { return {} },

  filters:{

    orderBy (){

      // doSomething

    },

    uppercase () {

      // doSomething

    }

  }

}

 

But we do the project, most of the filter is to be used globally, it is not often used to write the components inside, pumped into the global would be better. Official registration of the global fashion:

 

// Register

Vue.filter('my-filter', function (value) {

  // return value after treatment

})

// getter, returns the registered filter

var  myFilter = Vue.filter ( 'my-filter')

 

But then dispersed write unsightly, it can be extracted into separate files.

 

2.2 Optimization

 

We could draw off into a separate file and then use Object.keys unified registration at the entrance main.js

 

/src/common/filters.js

 

 

let dateServer = value => value.replace(/(d{4})(d{2})(d{2})/g, '$1-$2-$3')

 

export { dateServer }

 

/src/main.js

 

import * as custom from './common/filters/custom'

Object.keys(custom).forEach(key => Vue.filter(key, custom[key]))

 

In other then you can happily use them we defined a global filter file .vue

 

 

<template>

  <section class="content">

    <p>{{ time | dateServer }}</p> <!-- 2016-01-01 -->

  </section>

</template>

<script>

  export default {

    data () {

      return {

        time: 20160101

      }

    }

  }

</script>

 

3, the global component registration

 

3.1 General situation

 

It requires the use of components of the scene:

 

<template>

    <BaseInput  v-model="searchText"  @keydown.enter="search"/>

    <BaseButton @click="search">

        <BaseIcon name="search"/>

    </ BaseButton>

</template>

<script>

    BaseButton import from "./baseButton"

    import BaseIcon from './baseIcon'

    import BaseInput from './baseInput'

    export default {

      components: {BaseButton, silicon, BaseInput}

    }

</script>

 

We wrote a bunch of basic UI components, then every time we need to use these components, had to import, and then declare components, cumbersome, can be used here in the form of a unified registration

 

3.2 Optimization

 

We need to use what artifact webpack, use require.context () method to create their own modules context, in order to achieve the automatic dynamic require assembly. This method takes three parameters: the file folder you want to search the directory, whether it should also search subdirectories, as well as being a regular expression matching files. We add a file called componentRegister.js folder of files in components, with webpack dynamic in this document will be the basis of all package components that need to come in.

 

/src/components/componentRegister.js

 

Import view from 'View'

 

/**

* Capitalized

* @Param str String

* @example heheHaha

* <a href="http://www.jobbole.com/members/wx1409399284">@return</a> {string} HeheHaha

*/

function capitalizeFirstLetter(str) {

  return str.charAt(0).toUpperCase() + str.slice(1)

}

 

/**

* To comply 'xx / xx.vue' component assembly is removed name component format

* @param str fileName

* @example abc/bcd/def/basicTable.vue

* <a href="http://www.jobbole.com/members/wx1409399284">@return</a> {string} BasicTable

*/

function validateFileName(str) {

  return /^S+.vue$/.test(str) &&

    str.replace(/^S+/(w+).vue$/, (rs, $1) => capitalizeFirstLetter($1))

}

 

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

 

// Locate the file named .vue Components folder under the component name registration if the file name index, then take the name as a component

requireComponent.keys().forEach(filePath => {

  const componentConfig = requireComponent(filePath)

  const fileName = validateFileName(filePath)

  const componentName = fileName.toLowerCase() === 'index'

    ? capitalizeFirstLetter(componentConfig.default.name)

    : fileName

  Vue.component(componentName, componentConfig.default || componentConfig)

})

 

Here folder structure:

 

components

│ componentRegister.js

├─BasicTable

│ BasicTable.vue

├─MultiCondition

│ index.vue

 

Here the judgment made on the component name, if index would then take the name attribute of the processing components as the component name registration, so the final assembly registered as: multi-condition, basic-table at the end we main.js the import 'components /componentRegister.js', then we can use whenever and wherever these basic components, without having to manually introduced ~

 

4, component reuse different routes

 

4.1 Restore scene

 

When a scene vue-router from / post-page / a, jump to / post-page / b. Then our amazing discovery, after the page jump did not even update the data? ! The reason is vue-router "intelligently" found it to be the same component, then it is decided to reuse this component, so you write in the created function in the method never even execution. The usual solution is to monitor changes in $ route to initialize data, as follows:

 

data() {

  return {

    loading: false,

    error: null,

    post: null

  }

},

watch: {

  '$ route': {         // Use watch to monitor whether the same route

    Trades, 'reset data'

    immediate: true

  }

},

methods: {

  resetData() {

    this.loading = false

    this.error = null

    this.post = null

    this.getPost(this.$route.params.id)

  },

  getPost(id){ }

}

 

4.2 Optimization

 

In order to achieve this effect you can add a different key router-view, so that even the common components, as long as the url changed, they will re-create this component.

 

<router-view :key="$route.fullpath"></router-view>

 

You may also be added thereafter + + new Date () stamp for unique

 

Thanks friends remind @rolitter, if the component is placed <keep-alive> in, you can get the new data on the activated hook method, instead of the original mission, to get data in created mounted hooks.

 

 

5, components penetrate event properties

 

5.1 General situation

 

 

// parent component

<BaseInput :value="value"

           label = "password"

           placeholder = "Please fill in the password"

           @input="handleInput"

           @focus="handleFocus">

</BaseInput>

 

// Subassembly

<template>

  <label>

    {{ label }}

    <input :value=" value"

           :placeholder="placeholder"

           @focus="$emit('focus', $event)"

           @input="$emit('input', $event.target.value)">

  </label>

</template>

 

5.2 Optimization

 

Vue component instance in the $ props, $ attrs provides us with a great convenience, especially when the father and son by value components. 1, each sub-assembly passed a props from the parent component, we have to explicitly declare Props to use in the sub-assembly. As a result, we need to affirm sub-assemblies each time a lot of props, where we know that v-bind can pass an object, you can get all the props parent component of the value of v-bind in vm. $ Props in = " $ props "

 

 

<input  v-bind="$props"

       @input="$emit('input', $event.target.value)">

 

2, which is similar to placeholer dom native property can be reached using the $ attrs child, no direct statement from the parent. Methods as below:

 

 

<input :value="value"

       v-bind="$attrs"

       @input="$emit('input', $event.target.value)">

 

$ Attrs contains parent scope not recognized as a prop (and obtain) the binding properties (except for class and style). When a component does not declare any prop, where the binding will contain all the parent scope, and can be v-bind = "$ attrs" incoming internal components.

 

3, note that subcomponent @focus = "$ emit ( 'focus', $ event)" In fact, nothing to do, just put the event back to the parent component only, and that in fact, similar to the above, absolutely no need to explicitly stated:

 

 

<input :value="value"

       v-bind="$attrs"

       v-on="listeners"/>

 

computed: {

  listeners() {

    return {

      ...this.$listeners,

      input: event =>

        this.$emit('input', event.target.value)

    }

  }

}

 

$ Listeners contains the parent scope (excluding .native decorator) v-on event listener. It can be v-on = "$ listeners" Incoming internal components - very useful when creating a higher level of assembly.

 

It should be noted that, due to our input is not the root BaseInput this component, and the default characteristics are not recognized as props in the case of parent scope bindings will "back" and as an ordinary HTML attributes used in the subassembly the root element. So we need to set inheritAttrs: false, the default behavior will be removed, the above optimization to be successful.

 

 

6, according to the route state of development lazily

 

6.1 General situation

 

Generally, we loaded components in route time:

 

import Login from '@/views/login.vue'

 

export default new Router({

  routes: [{ path: '/login', name: '登陆', component: Login}]

})

 

When you need lazy loading , when the lazy-loading, requires a component to one of the routes () => import ( '@ / views / login.vue'), very troublesome.

 

When more and more of your project page, use in the development environment lazy-loading will become less suitable, each time you change the code to trigger hot update will become very slow. It is recommended that only routing lazy loading functionality in the build environment.

 

6.2 Optimization

 

The lazy loading code division function Webpack asynchronous component and may easily Vue the assembly, such as:

 

const Foo = () => import('./Foo.vue')

 

In distinguishing between development and production environments, you can create two files are in the routing folder:

 

_import_production.js

 

module.exports = file => () => import('@/views/' + file + '.vue')

 

_import_development.js (The wording vue-loader version least v13.0.0 above)

 

module.exports = file => require('@/views/' + file + '.vue').default

 

In setting up routes router / index.js file:

 

const _import = require('./_import_' + process.env.NODE_ENV)

 

export default new Router({

  routes: [{ path: '/login', name: '登陆', component: _import('login/index') }]

})

 

Such components in a development environment that is non-lazy loading, in a production environment is a lazy loading

 

 

7, vue-loader tips

 

vue-loader is processing * .vue file webpack loader. Which itself provides a rich API, API and some very practical but very few people are familiar with. For example preserveWhitespace and transformToRequire next to introduce

 

7.1 with a reduced file size preserveWhitespace

 

Sometimes we do not want to write a template when there are spaces between such elements may be written and elements:

 

<ul>

  <li>1111</li><li>2222</li><li>333</li>

</ul>

 

Of course there are other ways, such as setting the font of font-size: 0, then the content needs to set the font size alone, the purpose is to remove the space between the elements. In fact, we can achieve this requirement by configuring vue-loader.

 

{

  view: {

    preserveWhitespace: false

  }

}

 

Its role is to prevent the generation gap between element content, the use _v compiled Vue template ( "") represents. If the project template content and more, they will still take up some of the file size. Element configuration example after the property, when the compressed volume file is not reduced by nearly 30Kb.

 

7.2 transformToRequire no longer have to write the picture variables

 

In writing before the time of Vue often writes code like this: the picture in advance require to pass a variable and then to the assembly.

 

 

<template>

  <div>

    <avatar :default-src="DEFAULT_AVATAR"></avatar>

  </div>

</template>

<script>

  export default {

    created () {

      this.DEFAULT_AVATAR = require('./assets/default-avatar.png')

    }

  }

</script>

 

In fact, by arranging the transformToRequire, you can be configured directly, after such vue-loader will automatically require to pass attributes corresponding components

 

{

  view: {

    transformToRequire: {

      avatar: ['default-src']

    }

  }

}

 

So we can simplify a lot of code

 

 

<template>

  <div>

    <avatar default-src="./assets/default-avatar.png"></avatar>

  </div>

</template>

 

In the case webpack template vue-cli, the default configuration is:

 

transformToRequire: {

  video: ['src', 'poster'],

  source: 'src',

  img: 'src',

  image: 'xlink:href'

}

 

You can draw inferences about the conduct similar configuration

 

vue-loader and many useful API such as the recent addition of custom blocks, you may be interested to look for documentation.

 

8, render function

 

In some scenarios you may need to render to render fully programmable function capability to solve the problems brought about is not easy to solve, in particular, to dynamically generate labels and choose the component type scene.

 

8.1 Dynamic Label

 

1. General

 

According to such props to generate a scene tag

 

 

<template>

  <div>

    <div v-if="level === 1"> <slot></slot> </div>

    <p v-else-if="level === 2"> <slot></slot> </p>

    <h1 v-else-if="level === 3"> <slot></slot> </h1>

    <h2 v-else-if="level === 4"> <slot></slot> </h2>

    <strong v-else-if="level === 5"> <slot></slot> </stong>

    <textarea v-else-if="level === 6"> <slot></slot> </textarea>

  </div>

</template>

 

Wherein the level of the data is variable, there can be seen a lot of code repetition, if more complex logic, plus some bind more complicated and is determined herein may be utilized to render function is determined to be a tag to be generated.

 

2. Optimize

Use render method to generate where the corresponding tag according to the parameters above can be avoided.

 

 

<template>

  <div>

    <child :level="level">Hello world!</child>

  </div>

</template>

 

<script type='text/javascript'>

  Import view from 'View'

  Vue.component('child', {

    render(h) {

      const tag = ['div', 'p', 'strong', 'h1', 'h2', 'textarea'][this.level]

      return h(tag, this.$slots.default)

    },

    props: {

      level: {  type: Number,  required: true  }

    }

  })  

  export default {

    name: 'hehe',

    data() { return { level: 3 } }

  }

</script>

 

Examples can be viewed CodePen (https://codepen.io/SHERlocked93/pen/mLEJPE)

 

8.2 Dynamic Components

 

Of course render function, there are many uses, such as to use dynamic components, in addition to use: outside is also possible to use render function

 

 

<template>

  <div>

    <button @click='level = 0'>嘻嘻</button>

    <button @click='level = 1'>哈哈</button>

    <hr>

    <child :level="level"></child>

  </div>

</template>

 

<script type='text/javascript'>

  Import view from 'View'

  import Xixi from './Xixi'

  import Haha from './Haha'

  Vue.component('child', {

    render(h) {

      const tag = ['xixi', 'haha'][this.level]

      return h(tag, this.$slots.default)

    },

    props: { level: { type: Number, required: true } },

    components: { Xixi, Haha }

  })

  export default {

    name: 'hehe',

    data() { return { level: 0 } }

  }

</script>

 

Examples can be viewed CodePen (https://codepen.io/SHERlocked93/pen/YLWwxM)

 

Most online posts shades, and even some contradictory, the following articles are summarized in the process of learning, if error, found welcome message pointed out -

 

reference:

 

  • Vue2 global filter (vue-cli)
  • Vue.js Best Practices
  • webpack document - require.context
  • Use webpack of require.context implement routing "decentralized" management
  • vue-element-admin documentation
  • Vue.js practical tips
  • Optimization of the page to open the speed, you do not look ~

 

Guess you like

Origin www.cnblogs.com/pjblog-code/p/11456393.html