Migrating from Vue 1.x


Table of Contents

  • FAQ

  • Template

  • Lifecycle hook function

    • ##beforeCompile

    • ##compiled

    • attached

    • detached

    • ##init
    • ready
    ##v-for
  • v-for Parameter order when traversing an array
    • v-for Parameter order when traversing an object
    • $index and $key
    • ##track-by

    • v-for range value

    • ##Props
  • Parameters of coerce Prop

  • cache: false

    • ##Built-In directive

  • v-bind true/false value

    • Use v-on to listen to native events

    • v-model with debounce

    • V-model using lazy or number parameters

    • v-model using inline value

    • v-model with v-for Iterated Primitive Values

    • v-bind:style with !important

    • ##v-el and v-ref

    • Use v-else after v-show

  • ##Custom instructions

    • Directive.literal modifier

  • ##Transition

    • transition parameters

    • Reusable transition Vue.transition

    • Transition stagger parameters

  • ##Events
    • events Options
    • Vue.directive('on').keyCodes
    • $dispatch and $broadcast
    ##Filter
  • Insert filters outside text
    • Filter parameter symbols
    • Built-in text filter
    • Bidirectional filter
    Insert Slot
  • Slot with the same name
    • slot style parameter
    Special attributes
  • ##keep-alive attribute

    • Calculated interpolation
  • Computed interpolation inside the attribute

    • HTML calculation interpolation

    • Single binding

    • Response
  • vm.$watch

  • ##Instance methods around the DOM

    • vm.$appendTo

    • ##vm.$before

    • vm.$after

    • ##vm.$remove
  • Underlying instance methods
    • vm.$eval
    • vm.$interpolate
    • vm.$log
  • Instance DOM options
    • replace: false
    ## Global configuration
  • Vue.config.debug
  • ##Vue.extend with el

    • Vue.elementDirective

    • ##Vue.partial

    • ##FAQ


##Wow, a very long one Page! Does it mean that Vue 2.0 is completely different? Do you need to learn it from scratch? Is it impossible to migrate Vue 1.0 projects?

I am very happy to tell you that it is not! Almost 90% of the API and core concepts remain unchanged. This section is a bit long because it contains a lot of elaboration and many migration examples. Don't worry, You don't have to read this section from beginning to end!


Where should I start project migration?

1. First, run the
migration tool

under the current project. We've taken great care to simplify the advanced Vue upgrade process to using a simple command line tool. When the tool identifies a legacy feature, it notifies you and makes recommendations, along with links to more information.

 2. Then, browse the content listed in the sidebar of this page. If you find that some titles have an impact on your project, but the migration tool does not give a prompt, please check your project.

3. If your project has test code, run it and see where it still fails. If you don't have test code, open your application in a browser, navigate around and pay attention to any errors or warnings.

4. Your application should now be completely migrated. If you're eager to learn more, you can read the rest of this page - or start from the beginning in the Introduction section and dive into the new documentation and improved guidance. Many sections have been left out since you are already familiar with some of the core concepts.

How long does it take to migrate a Vue 1.x version application to 2.0?

This depends on several factors:

  • Depends on the size of your application (small and medium-sized ones can basically be done in one day) .

  • Depends on how many times you get distracted and start 2.0's coolest new feature. Can't tell the time, this happens often when we build 2.0 applications!

  • Depends on which old features you use. Most can be upgraded via find-and-replace, but some may take a while. If you don't follow best practices, Vue 2.0 will try its best to force you to follow them. This is good for the long term of the project, but may also mean significant refactoring (although some of the parts that need to be refactored may be obsolete).

If I upgrade to Vue 2, do I also have to upgrade Vuex and Vue Router at the same time?

Only Vue Router 2 is compatible with Vue 2, so Vue Router needs to be upgraded, and you must follow the Vue Router migration method to handle it. Fortunately, most applications don't have a lot of router-related code, so the migration probably won't take more than an hour.

For Vuex, version 0.8 remains compatible with Vue 2, so some parts do not have to be forced to upgrade. The only reason to upgrade now is if you want to take advantage of the new advanced features in Vuex 2, such as modules and reduced boilerplate.


template



Fragment instanceRemove

Each component must have only one root element. Fragment instances are no longer allowed, if you have a template like this:

<p>foo</p>
<p>bar</p>

It's better to simply wrap the entire content into a new element, like this:

<div>
  <p>foo</p>
  <p>bar</p>
</div>

Upgrade method

Run the end-to-end test suite (end-to-end test suite) or run the application after the upgrade, and Check console warnings to identify places in the template that have multiple root elements.


Life cycle hook function



##beforeCompile Remove

Use

created hook function instead.


##compiled replace Use

mounted

hook function instead.

Upgrade methodRun the

migration tool

in the code base to find all functions that use this hook example.


attached RemoveUse the DOM check method built into other hook functions. For example, replace the following:

attached: function () {
  doSomething()
}

can be used like this:

mounted: function () {
  this.$nextTick(function () {
    doSomething()
  })
}

Upgrade methodIn the code base Run the

Migration Tool

to find all examples that use this hook function.


##detached RemovedUse the DOM check method in other hook functions. For example, replace the following:

detached: function () {
  doSomething()
}

can be used like this:

destroyed: function () {
  this.$nextTick(function () {
    doSomething()
  })
}

Upgrade method

In the code base Run the Migration Tool

to find all examples that use this hook function.


##init#RenameUse the new

beforeCreate

hook function instead, essentially beforeCreate is exactly the same as init. init was renamed to be consistent with the naming of other lifecycle methods.


##readyreplace Use the new mounted

hook function instead. It should be noted that using

mounted does not guarantee that this.$el in the hook function is in the document. Vue.nextTick/vm.$nextTick should also be introduced for this purpose. For example:

mounted: function () {
  this.$nextTick(function () {
    // 代码保证 this.$el 在 document 中
  })
}

Upgrade method

Run the migration tool

in the code base to find out all uses Example of this hook function.


##v-for



v-for

Parameter order when traversing the array Change When index
is included, the order of parameters when traversing the array was

(index, value)

. It's now (value, index) to be consistent with JavaScript's native array methods (such as forEach and map).

Upgrade method

Run the migration tool in the code base to find out which files use the old parameters Example of sequence. Note that if you name your index parameter something unusual (such as

position

or num), the migration tool will not mark them out.


v-for## Parameter order when traversing the objectChange

When the property name/key is included, the parameter order of the previous traversal object is

(name, value). Now (value, name), to be consistent with common object iterators (such as lodash).


$index and $key Removed

The two implicit declarations

$index and $key have been removed Variables to be explicitly defined in v-for. This allows developers without much Vue development experience to better read the code and also results in cleaner behavior when dealing with nested loops.

Upgrade method

Run the

migration tool in the code base to find out the variables used to remove these example. If you don't find it, you can also look for it in Console Error (for example Uncaught ReferenceError: $index is not defined).


##track-by replacement

track-by

has been replaced with key which works like other properties without v-bind or : prefix, it will be treated as a string. In most cases, you will need to replace static keys with dynamic binding with full expressions. For example, to replace:

<div v-for="item in items" track-by="id">
you should now write:

<div v-for="item in items" v-bind:key="item.id">

Upgrade method in the code base Run the

Migration Tool

in to find examples that use track-by.


##v-for## Range valueChangeBefore, the

number

of v-for="number in 10" started from 0 and ended at 9, now it starts from 1 and ends at 10 .

Upgrade methodUse the regular

/\w in \d /

search in the code base. When present in v-for, please check if it is affected.


##Props



##coerce

Parameters of PropRemoveCheck if needed The value of prop creates an internal computed value instead of defining it inside props. For example:

props: {
  username: {
    type: String,
    coerce: function (value) {
      return value
        .toLowerCase()
        .replace(/\s+/, '-')
    }
  }
}
should now be written as:

props: {
  username: String,
},
computed: {
  normalizedUsername: function () {
    return this.username
      .toLowerCase()
      .replace(/\s+/, '-')
  }
}

This has some advantages:

You can maintain the operation permissions of the original prop value.

  • Force developers to use explicit declarations by giving the validated value a different name.

Upgrade method

Run the migration toolFind out the

An instance of the coerce

option.


#twoWay

Prop parametersMove Except Props can now only be passed in one direction. In order to have a reverse effect on the parent component, the child component needs to explicitly pass an event instead of relying on implicit two-way binding. For details, see:

Custom component event

  • Custom input component

    (Use component Event)
  • Global status management

  • ##Upgrade method

Run the migration tool to find the instance containing the twoWay parameter.


##v-bind## of .once and .sync ModifiersRemovedProps can now only be passed one way. In order to have a reverse effect on the parent component, the child component needs to explicitly pass an event instead of relying on implicit two-way binding. For details, see:

  • Custom component event

  • Custom input component

    (Use component Event)

  • Global status management

##Upgrade method

RunMigration Tool

Find instances using the .once and

.sync modifiers.


Modify Props

DeprecatedModify props within the component It's an anti-pattern (not recommended). For example, declare a prop first, and then change the prop's value in the component through this.myProp = 'someOtherValue'

. According to the rendering mechanism, when the parent component is re-rendered, the internal prop value of the child component will also be overwritten.

In most cases, changing the prop value can be replaced by the following options:

Through the data attribute, use prop to set the default value of a data attribute.
  • Through the computed attribute.
Upgrade method

Run the end-to-end test and view the controls on prop modification Station warning message

.


Props for the root instance

ReplacementFor a root For instances (for example: instances created with new Vue({ ... })

), you can only use

propsData instead of props.

Upgrade method

Run the end-to-end test, failed tests

will pop up to notify you to use The root instance of

props has expired.


Computed properties



##cache: false Deprecated

In future major versions of Vue , cache validation for computed properties will be removed. Converting uncached computed properties to methods yields the same results as before.

Example:

template: '<p>message: {{ timeMessage }}</p>',
computed: {
  timeMessage: {
    cache: false,
    get: function () {
      return Date.now() + this.message
    }
  }
}

Or use component method:

template: '<p>message: {{ getTimeMessage() }}</p>',
methods: {
  getTimeMessage: function () {
    return Date.now() + this.message
  }
}

##Upgrade method Run the

migration tool

and find the cache: false option.


##Built-In Command



v-bind True/False value Change ##When using v-bind
in 2.0, only

null

, undefined, and false are considered false . This means that 0 and the empty string will be rendered as true values. For example, v-bind:draggable="''" will be rendered as draggable="true". For enumeration properties, in addition to the above false values, the string "false" will also be rendered as

attr="false"

. Note that for other hook functions (such as v-if

and
v-show

), they still follow the general rules of js for judging true and false values. .

Upgrade method

Run end-to-end tests if any part of your app may be affected by this upgrade to, failed tests will pop up


Use

v-on

to listen for native eventsChangeNow using v-on on the component will only listen to custom events (events triggered by the component using

$emit

). If you want to listen to the native events of the root element, you can use the .native modifier, such as:

<my-component v-on:click.native="doSomething"></my-component>

Upgrade method

Run the migration tool in the code base to find all examples that use this hook function.


v-modelremove## with debounce

#Debouncing was once used to control the frequency of Ajax requests and other expensive tasks. The

debounce attribute parameters of v-model in Vue make it very easy to achieve this control in some simple cases. But in fact, this is to control the frequency of status updates, rather than to control the time-consuming task itself. This is a small difference, but will become limiting as your application grows.

For example, limitations when designing a search prompt:

1.gif

Using the

debounce parameter, you cannot observe the status of "Typing" . Because the input status cannot be detected in real time. However, by decoupling debounce from Vue, we can only delay the operations we want to control, thus avoiding these limitations:

<!--
通过使用 lodash 或者其它库的 debounce 函数,
我们相信 debounce 实现是一流的,
并且可以随处使用它,不仅仅是在模板中。
-->
<script src="https://cdn.jsdelivr.net/lodash/4.13.1/lodash.js"></script>
<div id="debounce-search-demo">
  <input v-model="searchQuery" placeholder="Type something">
  <strong>{{ searchIndicator }}</strong>
</div>
new Vue({
  el: '#debounce-search-demo',
  data: {
    searchQuery: '',
    searchQueryIsDirty: false,
    isCalculating: false
  },
  computed: {
    searchIndicator: function () {
      if (this.isCalculating) {
        return '⟳ Fetching new results'
      } else if (this.searchQueryIsDirty) {
        return '... Typing'
      } else {
        return '✓ Done'
      }
    }
  },
  watch: {
    searchQuery: function () {
      this.searchQueryIsDirty = true
      this.expensiveOperation()
    }
  },
  methods: {
    // 这是 debounce 实现的地方。
    expensiveOperation: _.debounce(function () {
      this.isCalculating = true
      setTimeout(function () {
        this.isCalculating = false
        this.searchQueryIsDirty = false
      }.bind(this), 1000)
    }, 500)
  }
})

Another advantage of this approach is: When the execution time of the wrapped function is equal to the delay time, it will wait for a long time. For example, when giving search suggestions, you have to wait for the user to stop inputting for a period of time before giving the suggestions, which is a very poor experience. In fact, it is more suitable to use the

throttling function at this time. Since you now have the freedom to use libraries like lodash, you can quickly refactor your project using throttling.

Upgrade Path

Run the

migration toolInstance using the debounce parameter.


v-model## using lazy or number parameters # . Replacement##lazy

and

number parameters are now used as modifiers, which makes it look clearer, while Not like this:

<input v-model="name" lazy>
<input v-model="age" type="number" number>
Now it’s written like this:
<input v-model.lazy="name">
<input v-model.number="age" type="number">

Upgrade method

Runmigration tool

Find these deprecated parameters.


v-model Remove# using inline value

##v-model no longer initializes the initial value inline value. Obviously, it will use the corresponding attribute of the instance's data as the real initial value. .

This means that the following elements:

<input v-model="text" value="foo">

Having the following in the data option:

data: {
  text: 'bar'
}

will render the model as 'bar' instead of 'foo' . Similarly, for the existing value of

<textarea>:

<textarea v-model="text">
  hello world
</textarea>

must ensure that the initial value of

text is "hello world"

Upgrade method

Run the end-to-end test after the upgrade, pay attention to

console warnings about v-modelinline parameters


##v-model with v-for Iterated Primitive Values ​​RemoveWriting like this will not work:

<input v-for="str in strings" v-model="str">

Because

< ;input>

will be compiled into js code similar to the following:

strings.map(function (str) {
  return createElement('input', ...)
})
In this way, the two-way binding of

v-model

will be invalid here. Assigning str to another value in the iterator is useless because it is just a variable inside the function. The alternative is that you can use an object array so that

v-model

can update the fields in the object synchronously, for example:

<input v-for="obj in objects" v-model="obj.str">

Upgrade methodRun the test. If your app is affected by this update, a failed tests prompt will pop up.


##v-bind:style Shift with !important Except for , writing like this will be invalid:

<p v-bind:style="{ color: myColor + ' !important' }">hello</p>

If you really need to cover other

!important

, it is best to use string form. Write:

<p v-bind:style="'color: ' + myColor + ' !important'">hello</p>

Upgrade method

Run Migration Help Tool

. Find the style binding object containing

!important.


v-el## and v-ref replace

For simplicity,

v-el and v-ref are combined into one ref attribute, which can be used in components In the example, it is called by $refs. This means v-el:my-element will be written like this: ref="myElement", v-ref:my-component becomes like this: ref="myComponent". When bound to a general element, ref refers to a DOM element. When bound to a component, ref is a component instance.

Because

v-ref is no longer an instruction but a special attribute, it can also be defined dynamically. This is useful when combined with v-for:

<p v-for="item in items" v-bind:ref="'item' + item.id"></p>

former

v-el/v-ref and v-for used together will produce a DOM array or array of components, since there is no way to give each element a specific name. You can still do this and give every element the same ref:

<p v-for="item in items" ref="items"></p>

Unlike in 1.x,

$refs is not responsive because They are registered/updated during rendering. Only listening for changes and rendering repeatedly can make them responsive.

On the other hand, the design

$refs is mainly provided for access by js programs, and it is not recommended to rely too much on it in templates. Because this means accessing instance state outside the instance, which goes against the data-driven thinking of Vue.

Upgrade method

Run

migration toolFind out v-el# in the instance ## and v-ref.


##v-showUse after v-else Removev-else

can no longer be used after

v-show . Please use v-show in the negative branch of v-if instead. For example:

<p v-if="foo">Foo</p>
<p v-else v-show="bar">Not foo, but bar</p>
should now be written like this:
<p v-if="foo">Foo</p>
<p v-if="!foo && bar">Not foo, but bar</p>

Upgrade method

RunMigration Tools

Find out

v-else and v-show that exist in the instance.


Custom instructionsSimplify


In the new version, the use of instructions The scope has been greatly reduced: now the directive is only used for low-level DOM manipulation. In most cases, it's best to use components as an abstraction layer for code reuse.

The significant changes are as follows:

  • Instructions no longer have instances. Meaning, you no longer have the instance's this in the directive's hook function. Instead, you can accept any data you need in the parameters. If you really need it, you can access the instance via el.

  • Similar to acceptStatement, deep, priority, etc. have been deprecated. To replace the bidirectional directive, see Example.

  • Now the meaning of some hooks is different from before, and there are two more hook functions.

Fortunately, the new hook is simpler and easier to master. See Custom Instructions Guide for details.

Upgrade method

Run the migration toolFind out where the directive is defined. The helper tool will mark these places because it is likely that these places need to be refactored.


Directive.literal ModifierRemove# The

##.literal modifier has been removed. To obtain the same functionality, you can simply provide the string modifier as the value.

Example, change as follows:

<p v-my-directive.literal="foo bar baz"></p>

Just:

<p v-my-directive="'foo bar baz'"></p>

##Upgrade method Run the

Migration Tool

to find out where the `.literal` modifier is used in the instance.


transition



transition Parameter Replacement

Vue’s transition system has been completely changed , transition effects are now achieved by wrapping elements with <transition> and <transition-group> instead of using the transition attribute. See Transitions guide for details.

Upgrade method

Run the migration toolFind the place where the transition attribute is used .


##Reusable transitionVue.transition Replacement

In the new transition system, you can

reuse transition effects through templates.

Upgrade method

Run the

migration toolFind the place where the transition attribute is used .


Transitionalstagger ParametersRemoved

If you wish to use a gradual transition in list rendering, you can control the timing by setting the element's

data-index (or similar attribute). Please refer to this example.

Upgrade method

Run the

migration toolFind the place where the transition attribute is used . During an upgrade, you can "transition" to a new transition strategy.


event



events OptionRemoved

events Option is deprecated . Event handlers are now registered in the created hook. Refer to detailed examples$dispatch and $broadcast Migration Guide


Vue.directive('on').keyCodes##Replacement

New concise configuration The way

keyCodes is through Vue.config.keyCodesFor example:

// v-on:keyup.f1 不可用
Vue.config.keyCodes.f1 = 112

Upgrade method

Run

Migration ToolFind outdated keyCode configuration


##$dispatch## and $broadcast Replacements

$dispatch

and $broadcast have been deprecated. Please use more concise and clear inter-component communication and better state management solutions, such as: Vuex. Because the event flow method based on the component tree structure is really difficult to understand, and will become more and more fragile as the component structure expands. This event method is really not good, and we don’t want to cause developers too much pain in the future. And

$dispatch

and $broadcast do not solve the communication problem between sibling components. The easiest way to upgrade

$dispatch

and $broadcast is to use event hubs to allow components to communicate freely, no matter what level they are in the component tree. . Since Vue instances implement an event dispatching interface, you can achieve this by instantiating an empty Vue instance. One of the most common uses of these methods is for parent-child components to communicate with each other. In these cases, you can use

v-on

Listen for changes to $emit on the child component. This allows you to easily add event visibility. However, if the communication is across multiple layers of parent-child components,

$emit

is of no use. In contrast, using centralized event middleware allows for simple upgrades. This makes communication between components very smooth, even if they are siblings. Because Vue executes instances through the event emitter interface, you can actually use an empty Vue instance. For example, suppose we have a todo application structure as follows:

Todos
├─ NewTodoInput
└─ Todo
   └─ DeleteTodoButton

You can manage communication between components through a separate event center:

// 将在各处使用该事件中心
// 组件通过它来通信
var eventHub = new Vue()

Then in the component, you can Use

$emit

, $on, $off to distribute, monitor, and cancel listening events respectively:

// NewTodoInput
// ...
methods: {
  addTodo: function () {
    eventHub.$emit('add-todo', { text: this.newTodoText })
    this.newTodoText = ''
  }
}
// DeleteTodoButton
// ...
methods: {
  deleteTodo: function (id) {
    eventHub.$emit('delete-todo', id)
  }
}
// Todos
// ...
created: function () {
  eventHub.$on('add-todo', this.addTodo)
  eventHub.$on('delete-todo', this.deleteTodo)
},
// 最好在组件销毁前
// 清除事件监听
beforeDestroy: function () {
  eventHub.$off('add-todo', this.addTodo)
  eventHub.$off('delete-todo', this.deleteTodo)
},
methods: {
  addTodo: function (newTodo) {
    this.todos.push(newTodo)
  },
  deleteTodo: function (todoId) {
    this.todos = this.todos.filter(function (todo) {
      return todo.id !== todoId
    })
  }
}
In a simple case, this is the case Do can replace

$dispatch

and $broadcast, but for most complex situations it is recommended to use a dedicated state management layer such as: Vuex.

Upgrade methodRun

Migration tool

Find out how to use $dispatch and Instance of $broadcast.


filter



Filter outside inserted textRemoved

Now the filter can only be used inside inserted text({{ }}tags). We found that using filters in directives (eg: v-model, v-on, etc.) made things more complicated. For list filters like v-for it is best to put the processing logic in js as a computed property so that it can be reused throughout the template.

In short, for things that can be implemented in native js, we try to avoid introducing a new symbol to repeatedly deal with the same problem. Here's how to replace Vue's built-in filters:


Replace debounce Filter

No longer written like this

<input v-on:keyup="doStuff | debounce 500">
methods: {
  doStuff: function () {
    // ...
  }
}

Please use lodash's debounce (or maybe throttle) to directly control high-consuming tasks. You can achieve the above function like this:

<input v-on:keyup="doStuff">
methods: {
  doStuff: _.debounce(function () {
    // ...
  }, 500)
}

For more advantages of this writing method, see: v-model Example.


Replace limitBy filter

no longer written like this:

<p v-for="item in items | limitBy 10">{{ item }}</p>

in Use the js built-in method in the computed attribute: .slice method:

<p v-for="item in filteredItems">{{ item }}</p>
computed: {
  filteredItems: function () {
    return this.items.slice(0, 10)
  }
}


## replace filterByFilter

No longer written like this:

<p v-for="user in users | filterBy searchQuery in 'name'">{{ user.name }}</p>

Use the js built-in method

.filter method:## in the computed attribute #

<p v-for="user in filteredUsers">{{ user.name }}</p>
computed: {
  filteredUsers: function () {
    var self = this
    return self.users.filter(function (user) {
      return user.name.indexOf(self.searchQuery) !== -1
    })
  }
}
js native

.filter

can also implement many complex filter operations, because all js methods can be used in computed properties. For example, to find users by matching their names and email addresses (case-insensitive):

var self = this
self.users.filter(function (user) {
  var searchRegex = new RegExp(self.searchQuery, 'i')
  return user.isActive && (
    searchRegex.test(user.name) ||
    searchRegex.test(user.email)
  )
})


replace the

orderBy filter Instead of writing:

<p v-for="user in users | orderBy 'name'">{{ user.name }}</p>

Instead use

lodash's

orderBy (or maybe ## in the computed attribute #sortBy):

<p v-for="user in orderedUsers">{{ user.name }}</p>
computed: {
  orderedUsers: function () {
    return _.orderBy(this.users, 'name')
  }
}
You can even sort by fields:
_.orderBy(this.users, ['name', 'last_login'], ['asc', 'desc'])

Upgrade method

RunMigration Tool

Find the filter used in the directive. If some are not found, look at

Console error messages.


Filter parameter notationChanges

The filter parameter form now works better The method of calling the js function is the same, so there is no need to separate the parameters with spaces:

<p>{{ date | formatDate 'YY-MM-DD' timeZone }}</p>

Now use parentheses and separate them with commas:

<p>{{ date | formatDate('YY-MM-DD', timeZone) }}</p>

Upgrade method

Run the migration tool to find the old calling symbols. If any are missing, please see the console error message.


Built-in text filterRemoved

Although the filter inserted inside the text remains Works, but all built-in filters have been removed. Instead, it is recommended to use more specialized libraries for each area. (For example, use date-fns to format the date and accounting to format the currency).

For each built-in filter, we roughly summarize how to replace it. Code examples may be written in custom helper functions, methods, or computed properties.


Replace json Filter

No need to change one by one, because Vue has automatically formatted it for you Okay, whether it's a string, a number, an array, an object. If you want to use the JSON.stringify function of js to implement it, you can also write it in a method or calculated attribute.


Replace capitalize filter

text[0].toUpperCase() + text.slice(1)


Replaceuppercase filter

text.toUpperCase()


Replacelowercase filter

text.toLowerCase()


Replace pluralize filter

The pluralize library on NPM can achieve this very well Function. If you just want to format specific words into the plural form or want to specify specific output for a specific value ('0'), you can also easily customize the plural formatting filter:

function pluralizeKnife (count) {
  if (count === 0) {
    return 'no knives'
  } else if (count === 1) {
    return '1 knife'
  } else {
    return count + 'knives'
  }
}


Replacing the currency Filter

For simple questions, you can do this:

'$' + price.toFixed(2)

In most cases, still There will be strange phenomena (for example, 0.035.toFixed(2) rounds up to get 0.04, but 0.045 rounds down to get 0.04). To solve these problems, you can use the accounting library to achieve more reliable currency formatting.

Upgrade method

Run migration toolFind the discarded filter. If something is missing, please refer to Console Error Messages.


Bidirectional filter Replacement

Some users have been happy to pass v- model Use bidirectional filters to create interesting inputs with very little code. Although simple on the surface, bidirectional filters can hide some huge complexities—even making status updates sluggish and impacting the user experience. It is recommended to use a component that wraps an input instead, allowing you to create custom inputs in a more explicit and feature-rich way.

Let's now do a two-way exchange rate filter migration as a demonstration:

It basically works well, but delayed status updates can cause weirdness the behavior of. For example, click the Result tag and try entering 9.999 in one of the input boxes. When the input box loses focus, its value will be updated to $10.00. However when we look at the entire calculator, you will find that the data stored is 9.999. What users see is no longer true synchronization!

To transition to a more robust Vue 2.0 solution, let's first wrap this filter in a new <currency-input> component:

It allows us to add behaviors that cannot be encapsulated by independent filters, such as selecting the content of the input box focus. Next we extract the business logic from the filter. Next we put everything into an external currencyValidator object:

This will be more Modularity not only makes migration to Vue 2 easier, but also allows for rate gaps and formatting:

  • Unit testing independently from your Vue code

  • Use it in other parts of your application, such as verifying the load of an API end

After extracting this validator, we can also update it Feel comfortable building it into a more robust solution. Those weird states are also eliminated, and users are no longer likely to enter errors, just like the browser's native number input box.

However, in the filters of Vue 1.0, we are still limited, so it is better to completely upgrade to Vue 2.0:

You You may have noticed:

  • Every aspect of our input box is more explicit, using lifecycle hooks and DOM events to replace the hidden behavior of bidirectional filters.

  • We can now use v-model directly in the custom input box. It is not only used with the normal input box, it also means that we The components are Vuex friendly.

  • Because we no longer require that the filter option must have a return value, our exchange rate work can actually be completed asynchronously. This means that if we have many applications that deal with exchange rates, we can easily refine this logic and make it a shared microservice.

Upgrade method

Run Migration toolFind in example Example of using filters in v-model directive. If you miss it, you should get a command line error.


##Slot



Slots with duplicate namesRemove

Duplicate names in the same template

<slot> Deprecated. Once a slot has been rendered, it cannot be rendered again elsewhere in the same template. If you want to render the same content in different locations, you can use prop to pass it.

Upgrade method

Run the test after the update and check the

console warning message About slots with the same name Tip v-model.


slot Style parametersRemove

Fragments inserted via named

<slot> no longer maintain the parameters of slot. Please use a wrapping element to control styling. Or take a more advanced approach: modify the content programmatically: render functions.

Upgrade method

Run

Migration toolFind the select slots tag CSS selector (for example: [slot="my-slot-name"]).


Special attributes



##keep-alive Attribute Replace

keep-alive It is no longer a special attribute but a wrapped component, similar to <transition>For example:

<keep-alive>
  <component v-bind:is="view"></component>
</keep-alive>

This can be used in subcomponents with multiple states

<keep-alive>:

<keep-alive>
  <todo-list v-if="todos.length > 0"></todo-list>
  <no-todos-gif v-else></no-todos-gif>
</keep-alive>

When

<keep-alive> contains different sub-components, each sub-component should be affected separately. Not just the first but all child components will be ignored.

When used together with

<transition>, make sure to wrap the content:

<transition>
  <keep-alive>
    <component v-bind:is="view"></component>
  </keep-alive>
</transition>

##Upgrade methodRun the

migration tool

Find the keep-alive attribute.


Calculate interpolation



##Computed interpolation inside the attribute

RemovedThe calculated interpolation inside the attribute can no longer be used:

<button class="btn btn-{{ size }}"></button>

should be written as an inline expression:

<button v-bind:class="'btn btn-' + size"></button>

or a calculated attribute:

<button v-bind:class="buttonClasses"></button>
computed: {
  buttonClasses: function () {
    return 'btn btn-' + size
  }
}

Upgrade method

Run Migration tool

Find the calculated interpolation inside the attribute


##HTML calculated interpolation

Remove

HTML computed interpolation ({{{ foo }}}) has been removed and replaced by the

v-html directive .

Upgrade method

Run Migration toolFind the HTML to calculate the interpolation.


Single BindingReplace

##Single Binding(

{ {* foo }}) has been replaced by the new v-once directive.

Upgrade method

Run

Migration toolFind the location where single binding is used.


response



vm.$watch changed

Passed

Observers created by vm.$watch will now be activated when the component renders. This allows you to update the state before the component is rendered without making unnecessary updates. For example, you can update the value of the component itself by observing changes in the component's props.

If you used to interact with the DOM after component updates through

vm.$watch, you can now do this through updated life cycle hooks.

Upgrade method

Run the test. If there are observers that depend on the old method, failed tests will pop up.


##vm.$set Change

vm.$set

is just an alias for Vue.set.

Upgrade methodRun

Migration tool

Find outdated usage


vm.$delete##Changevm.$delete

is now just:

Vue.delete Alias.

Upgrade method

RunMigration tool

Find obsolete usage


Array.prototype.$set Deprecated

Use Vue. set Alternative

Upgrade method

Run migration toolFind the on the array .$set. If there is anything missing, please refer to Console Error Message.


##Array.prototype.$remove Remove

Replace with

Array.prototype.splice, for example:

methods: {
  removeTodo: function (todo) {
    var index = this.todos.indexOf(todo)
    this.todos.splice(index, 1)
  }
}

or better way, remove it directly The method has an index parameter:

methods: {
  removeTodo: function (index) {
    this.todos.splice(index, 1)
  }
}

Upgrade method

Run

Migration toolFind the # on the array ##.$remove. If there is anything missing, please refer to Console Error Message.


##Vue.set and Vue.delete on the Vue instance RemoveVue.set

and

Vue.delete will no longer work on the instance. It is now mandatory to declare all top-level response values ​​in the instance's data option. If you delete an instance attribute or a value on instance$data, just set it to null.

Upgrade method

Run Migration tool

Find

Vue.set## in the instance # or Vue.delete. If there is anything missing, please refer to Console Error Message.

##Replace
vm.$data

RemoveReplacement of instance $data is now prohibited. This prevents the response system from some edge cases and makes the component state more controllable and predictable (especially for systems with type checking).

Upgrade method

Run Migration toolFind the coverage vm.$data

s position. If there is anything missing, please refer to

Console Warning Message.


##vm.$get##removeThe response data can be retrieved directly.

Upgrade methodRun

migration tool

Find vm.$get Location. If there is anything missing, please refer to Console Error Message.


Instance methods around the DOM



vm.$appendTo Remove
Use DOM native method:

myElement.appendChild(vm.$el)

Upgrade methodRun

Migration tool

Find # The location of ##vm.$appendTo. If there is anything missing, please refer to Console Error Message.


##vm.$before

Move Except ## use DOM native method:

myElement.parentNode.insertBefore(vm.$el, myElement)

Upgrade method

Run Migration Tool Find vm.$before

. If anything is missing, please refer to

Console Error Message.

##vm.$after

Move Except use DOM native method:

myElement.parentNode.insertBefore(vm.$el, myElement.nextSibling)
If myElement is the last node, you can also write like this:
myElement.parentNode.appendChild(vm.$el)

Upgrade method

Run migration toolFind the location of vm.$after. If anything is missing, please refer to

Console Error Message

.


##vm.$remove remove

Use DOM native method:

vm.$el.remove()

Upgrade method

Run

Migration Toolsfindvm.$remove. If anything is missing, please refer to Console Error Message.


Underlying instance methods



vm.$eval Remove

As much as possible Don't use it, if you must use this feature and are not sure how to use it please refer to

the forum.

Upgrade method

Run

Migration toolFind and use vm.$eval s position. If there is anything missing, please refer to Console Error Message.


##vm.$interpolateshift Try not to use it except ##. If you must use this function and are not sure how to use it, please refer to the forum

.

Upgrade method

Run migration tool

Find

vm.$interpolate. If there is anything missing, please refer to Console Error Message.


##vm.$log

Move In addition to , please use Vue Devtools to experience the best debugging experience.

Upgrade method

Run migration toolFind

vm.$log

. If anything is missing, please refer to the console error message.


Instance DOM Options



##replace: false Remove

Now the component will always Replace the elements they are bound to. To imitate the behavior of

replace: false, you can wrap the root component with an element similar to the element to be replaced:

new Vue({
  el: '#app',
  template: '<div id="app"> ... </div>'
})

or use the rendering function:

new Vue({
  el: '#app',
  render: function (h) {
    h('div', {
      attrs: {
        id: 'app',
      }
    }, /* ... */)
  }
})

Upgrade method

Run

Migration toolFind the location where replace: false is used.


Global configuration



##Vue.config.debug Remove
No longer required, because warning messages will be output in the stack message by default.

Upgrade methodRun

Migration tool

Find the file containing Vue.config.debugThe place.


##Vue.config.async## RemovedAsynchronous operations now require rendering performance support.

Upgrade method

RunMigration toolFind and use

Vue.config.async

instance.


##Vue.config.delimiters

## Replace with template options. This avoids affecting third-party templates when using custom separators.

Upgrade method

RunMigration toolFind and useVue.config.delimiters instance.


##Vue.config.unsafeDelimiters Remove

HTML interpolation

is replaced with v-html.

Upgrade method

Run the

migration tool to find Vue.config.unsafeDelimiters. Then the helper tool will also find instances of HTML insertion, which can be replaced with `v-html`.


##Global API



##Vue.extend withelremove
el option is not Then use it in

Vue.extend

. Available only in instance creation parameters.

Upgrade methodRun the test after updating and find out about the problem with # in the

console warning message

##Vue.extend of el.


##Vue.elementDirective

Remove Use components instead

Upgrade method

RunMigration Tool Find the instance containing

Vue.elementDirective

.


##Vue.partial##Remove Partials have been removed and replaced with more explicit data flow between components – props. Unless you are using a partially performance-critical area, it is recommended to just use a

normal component

instead. If you are dynamically binding part name, you can use dynamic component. If you happen to use partials in performance-critical parts of your application, then you should upgrade to

Functional components

. They must be in pure JS/JSX files (not in .vue files) and be stateless and instanceless, just like partials. This makes rendering extremely fast. One benefit of functional components over partials is that they can be more dynamic because they allow you to access the full power of JavaScript. However, this comes at a cost. If you've never used a rendered component framework, it may take you longer to learn them.

Upgrade methodRun

Migration tool

Find the file containing Vue.partial Example