Web Front-end Notes - Vuejs 2 Practice
- Vue CLI
- Setup a Vue CLI project
- Vue Caveats
Vue CLI
There are several components included in Vue CLI:
CLI
The CLI: @vue/cli
, provides vue
command in terminal.
CLI Service
The CLI Service: @vue/cli-service
, a development dependency, built on top of webpack
adn webpack-dev-server
, it contains:
- The core service that loads other CLI plugins
- An internal webpack config that is optimized for most apps
- The
vue-cli-service
binary inside the project, which comes with the basicserve
,build
andinspect
commands
See more detailed usage on (CLI Service)[https://cli.vuejs.org/guide/cli-service.html]
CLI Plugins
CLI Plugins are npm packages that provide optional features to your Vue CLI projects, such as Babel/TypeScript transpilation, ESLint integration, unit testing, and end-to-end testing. It’s easy to spot a Vue CLI plugin as their names start with either @vue/cli-plugin-
(for built-in plugins) or vue-cli-plugin-
(for community plugins).
When you run the vue-cli-service
binary inside your project, it automatically resolves and loads all CLI Plugins listed in your project’s package.json
. See more details in Plugins and Presets.
CLI Presets
A Vue CLI preset is a JSON object that contains pre-defined options and plugins for creating a new project so that the user doesn’t have to go through the prompts to select them. Presets saved during vue create
are stored in a configuration file in your user home directory (~/.vuerc)
. You can directly edit this file to tweak / add / delete the saved presets. See more details in CLI Presets.
Setup a Vue CLI project
Install vue cli
via npm:
1 | npm install -g @vue/cli @vue/cli-service-global |
Integrate with Webpack
Create a vue.config.js
file and specify a configureWebpack
function property, where a config
parameter is passed and return an object of webpack. We can play around with all webpack configurations inside this object.
Debug typescript and vuejs in vs code
Let TypeScript generate source maps. To this end, add the following to the “compilerOptions” section of your “tsconfig.json”:
1 | "sourceMap": true |
Let’s say we’d like to debug our code for chrome browser. Install Debugger for Chrome
extension in vscode. Switch to Debug View(Ctrl + Shift + D), here are the profiles of the debug configuration, click Run and Debug
will create a .vscode/launch.json
file under the project root folder.
When debugging a Vue project, vs code works together with webpack source map, go to vue.config.js
file, add devtool: 'source-map'
to configureWebpack
section, see more details about webpack devtool here.
Vue Caveats
The original Vuejs documentation mentioned:
It should be noted that properties in
data
are only reactive if they existed when the instance was created.
Same thing mentioned at the Vue Class Componenet documentation
Note that if the initial value is
undefined
, the class property will not be reactive, which means the changes for the properties will not be detected
We should always give an initial value on defining a property in data
object if we want to keep it reactive.
For Vuex, it is stated as well in their documentation:
The data you store in Vuex follows the same rules as the data in a Vue instance
When working with the vue-class-component
lib, fields in a Vue component class and a Vuex module class, will be considered as data properties/state properties. Keep in mind that defining a class field without giving a initial value will not keep it reactive after it’s translated into Vue components/store.
Array properties
For array properties, it is mentioned here that replacing an array is fine.
Vue cannot detect the following changes to an array:
- When you directly set an item with the index, e.g.
vm.items[indexOfItem] = newValue
- To overcome this, use
$vm.set | Vue.set(vm.items, indexOfItem, newValue)
orvm.items.splice(indexOfItem, 1, newValue)
instead.
- To overcome this, use
- When you modify the length of the array, e.g.
vm.items.length = newLength
- To overcome this, use
vm.items.splice(newLength)
instead
- To overcome this, use
Object properties
- Vue cannot detect property addition or deletion, a property must be present in the data object in order for Vue to convert it and make it reactive
- Vue does not allow dynamically adding new root-level reactive properties to an already created instance. However, it’s possible to add reactive properties to a nested object using the
this.$set | Vue.set(vm.someObject, 'b', 2)
- To assign a number of properties to an existing object, new properties added to the object will not trigger changes.
- To overcome this, use
this.someObject = Object.assign({}, this.someObject, { a: 1, b: 2 })
instead.
- To overcome this, use
See more details at Reactivity in Depth.
Vue Component/Vue Instance
Every Vue component is an individual instance of Vue, when calling new Vue({})
or Vue.Component("<component-name>", {})
to create a new Vue instace, the object argument include the following options configurable:
el
: The CSS selector of the Vue app root elementdata
: receive an object and adds all properties found in the object to Vue’s reactivity system. NOTE: You may see data receives an object in root Vue instance while a function which returns an object in components. This is because root Vue instance only orrcurs once, while components could have multiple instances, this makes sure that each component instance can maintain an independent copy of the returned data object.props
:propsData
:computed
: See belowmethods
: See belowwatch
:
Properties prefixed with a
$
are the native VueJS properties or methods.
How VueJS manages Data and Methods
Vue instance will only creates watchers for everything passed in the object upon creation with Vue constructor. Properties attached to Vue instance thereafter are not reactive.
$el
: It refers to the HTML template, the HTML code of that instance.$data
: It refers to the data block we passed on Vue instance creation and made accessible from outside, it points to the same reference of the data object,data === vm.$data
returns true.refs
: VueJS adds an HTML attributeref
used to register the HTML element tovm.$refs
property, which makes it easy to manipulate DOM from Vue instance Javascript code. However,vm.$refs.heading.innerText = 'something else'
does not overwrite the Vue template code, whenever VueJS re-renders the DOM, it takes its old template and re-renders the DOM based on the old template. Be aware any changes via$refs
property directly interact with the DOM, it is not reactive.
Mounting a template
We can use vm.$mount('#app')
method to mount the Vue intance to a specific HTML element with a CSS selector. This makes it possible to mount the HTML template programmatically.
Or we can set value to template
property in the constructor argument.
VueJS Intance Lifecycle
Lifecycle methods are not inside methods
property, they are all registered directly on the root object.
beforeCreate()
: occurred before Vue instance creation.created()
: occurred after Vue instance creation.beforeMount()
:mounted()
: The instance is attached to the real DOM.beforeUpdate()
: Data change detected, before updating the DOM.updated()
:beforeDestroy()
:destroyed()
: Vue instance is dead, do some clean up.
Computed Properties
This is how a computed property is defined:
1 | var vm = new Vue({ |
Computed Property vs. Methods
Instead of using a computed property, we can define the same function as a method. For the end result, the two approaches are indeed exactly the same. However, the difference is that computed properties are cached based on their reactive dependencies. A computed property will only re-evaluate when some of its reactive dependencies have changed. In comparison, a method invocation will always run the function whenever a re-render happens.
Computed Property vs. Watch
When you have some data that needs to be changed based on some other data, it falls easily to abuse watch
. However, it is often a better idea to use a computed property rather than an imperative watch
callback:
1 | // The Watch approach |
Plugins
In addition to vue components, there might be other types of logic blocks(services, utilities) that handle specific parts of the application. In order to expose the feature of those blocks, we can use plugins to act as the glue.
Define a plugin class in typescript
1 | interface SomePluginOptions { |
Plugin attach the service instance to either Vue global property or Vue instance property, install
method signature is a must to define a plugin. To make the service typescript friendly, we also extend the vue definition file:
1 | declare module "vue/types/vue" { |
Use Functional Components
Functional component is a stateless component without states and this
keyword, it acts as a wrapper of its children in most cases. To get started with functional component, the functional:true
property of the component option object is required:
1 | const options: FunctionalComponentOptions< |
The “key” Attribute
The key
special attribute is primarily used as a hint for Vue’s virtual DOM algorithm to identify VNodes when diffing the new list of nodes against the old list. Without keys, Vue uses an algorithm that minimizes element movement and tries to patch/reuse elements of the same type in-place as much as possible. With keys, it will reorder elements based on the order change of keys, and elements with keys that are no longer present will always be removed/destroyed.