1.Vue.extend(options)
Constructors , Create a Subclass . Parameter is an object containing component options
data Options are special cases , We need to pay attention to stay Vue.extend() It must be a function ,
<div id="test"></div>
// Create a constructor let MyTest = Vue.extend({ template: '<p>{{name}} {{age}}</p>', data(){ return { name: 'zhangning', age: '24' } } })
establish MyTest example , And mount it on an element
new MyTest().$mount('#test')
The final results are as follows
<p>zhangning 24</p>
above extend Created is Vue Constructors , Instead of a specific component instance , So it can't pass new Vue({components: testExtend}) For direct use , Need to pass through new MyTest().$mount('#test') To mount to the specified element
* call Vue.extend() What is created is a component constructor
* Usually when you create a component constructor , Pass in template The template that represents our custom component
* The template is where components are used , To show HTML Code
* however , It's written in vue2 After that, it was almost no longer used , They use grammar sugar directly , But we still have to learn , Lay the foundation for later study
Now we don't usually use Vue.extend() To register components , Use the grammar of sugar , Put the object directly in Vue.component() To register components , You can see the 7 individual API To study
call Vue.component() Register the component builder as a component , And give it a tag name for the component
So you need to pass two parameters :1. Register the tagnames of components 2. Component builder
The component must be attached to some Vue For example , Otherwise it will not take effect
Example : Encapsulate a global prompt component
First create a message.vue Components
<template> <transition> <div v-show='show'>{{message}}</div> </transition> </template> <script> export default{ data(){ return { show: false, message: '' } } } </script> <style scoped>
div {
padding: 10px;
color: #ddd;
background: red;
text-align: center;
position: fixed;
top: 30%;
left: 50%;
} </style>
And then in main.js Middle configuration
import Message from './components/Message.vue' const MessageM = { install: function(Vue) { // Create a vue Subclass components of const MessageConstructor = Vue.extend(Message) // Create subclass instances , And mount it to dynamically created elements , And add elements to the global structure const inst = new MessageConstructor().$mount(document.createElement('div')) document.body.appendChild(inst.$el) // stay vue Registration method on prototype chain , Control components Vue.prototype.$message = (msg, time = 1000) => { inst.message = msg inst.show = true setTimeout(( inst.show = false ), time) } } }
Vue.use(MessageM)
Use in components
this.$message(' Message tip ')
The above is a simple global message prompt
2.Vue.nextTick
Writing words DOM A delayed callback is executed after the update loop is completed . Use this method immediately after modifying the data , Gets the updated DOM
<template> <div> <div ref='valRef'>{{ val }}</div> <div>{{ val1 }}</div> <div>{{ val2 }}</div> <div>{{ val3 }}</div> <el-button type="primary" @click.once='handleClick'> change val</el-button> </div> </template> <script> export default { name: 'index', data() { return { val: 'zhangning', val1: '', val2: '', val3: '' } }, methods: { // When you click the button ,val1 and val3 It is obtained at the time of initial loading val Value , because vue Of DOM Is asynchronous load , // And used nextTick Of val2 The value of the msg After change , And immediately got val Updated value handleClick() { this.val = ' I've changed '; // DOM Not updated , You can't get the latest dom this.val1 = this.$refs.valRef.innerHTML; this.$nextTick(() => { // DOM Updated , Get the latest dom this.val2 = this.$refs.valRef.innerHTML; }) // DOM Not updated , You can't get the latest dom this.val3 = this.refs.valRef.innerHTML; } } } </script>
Official explanations and examples ( Asynchronous update queue )
Vue Updating DOM Time is executed asynchronously . Just listen for data changes ,Vue A queue will be opened , And buffer all data changes that occur in the same event cycle , If the same watcher Triggered multiple times , Will only be pushed into the queue once . This de duplication of data in buffering avoids unnecessary computation and DOM Operation is very important . However, in the next event loop tick in ,Vue Refresh the queue and execute the actual ( Has gone to heavy ) Work .Vue Try using native... Internally for asynchronous queues Promise.then、MutationObserver and setImmediate, If the execution environment does not support , Will use setTimeout(fn, 0) Instead of .
for example , When setting vm.someData = 'newVlaue', The component does not re render immediately , When refreshing the queue , The component will cycle through the next event tick In the update . Most of the time we don't need to care about the process , But if you want to be based on the updated DOM State, do something , It's a little tricky . although Vue Encourage us to think in a data-driven way , Avoid direct contact DOM , But sometimes we have to do this . To wait after the data changes Vue Update complete DOM, It can be used immediately after data changes Vue.nextTick(callback). So the callback function will be in DOM It is called after the update is completed . for example
<div id="example">{{message}}</div>
var vm = new Vue({ el: '#example', data: { message: '123' } }) vm.message = 'new message' // Change data vm.$el.textContent === 'new message' // false Vue.nextTick(function () { vm.$el.textContent === 'new message' // true })
Use in components vm.$nextTick() Example method is particularly convenient , Because it doesn't need to be global Vue , And call back the this Automatically bind to the current Vue For instance
Vue.component('example', { template: '<span>{{ message }}</span>', data: function () { return { message: ' Not updated ' } }, methods: { updateMessage: function () { this.message = ' Updated ' console.log(this.$el.textContent) // => ' Not updated ' this.$nextTick(function () { console.log(this.$el.textContent) // => ' Updated ' }) } } })
because $nextTick() Return to one Promise object , So you can use the new grammar async/await Do the same thing
methods: { updateMessage: async function () { this.message = ' Updated ' console.log(this.$el.textContent) // => ' Not updated ' await this.$nextTick() console.log(this.$el.textContent) // => ' Updated ' } }
3.Vue.set
Vue.set(target, key, value)
target: The data source to change ( It can be an object or an array )
key: Specific data to be changed
value: A new value
because js The limitation of ,Vue Can't detect changes in data , But modify the data in the array in this way , Changes to the array will be detected , It's reactive
usage : Add a property, And make sure this new property It's also responsive , And trigger view update . It must be used to add new property, because Vue Can't detect normal additions property ( such as arr[1] = 110)
export default { name: 'index', data() { return { arr: [1,2,3] } }, methods: { // modify arr[1] Turn into 200 handleChange(){ this.$set(this.arr, 1, 200);// arr: [1, 200, 3] }, // arr Array add elements 600 handleAddArr(){ this.$set(this.arr, this.arr.length, 600); } } }
4.Vue.delete()
Vue.delete(target, key, value)
target: Data source to delete ( It can be an object or an array )
key: Specific data to be deleted
usage : Delete object's property. If the object is responsive , Make sure the deletion triggers the update view . This method is mainly used to avoid Vue Can't detect property Removed restrictions , Although rarely used , But until you know how to use
export default { name: 'index', data() { return { zhangning: { height: 187, name: 'zhangning', sex: ' male ' } } }, methods: { // Delete name handleDeleteName() { this.$set(this.zhangning, 'name'); } } }
5.Vue.directive()
Vue.directive(string, Function | Object)
Register or get global instructions
Declaration period :
bind: Call it once , The first time an instruction is bound to an element . Here you can do one-time initialization settings .
inserted: Called when the bound element is inserted into the parent node ( Only the parent node is guaranteed to exist , But it doesn't have to be inserted into the document )
update: Of the component VNode Call when updating , But it could happen in its son VNode Before updating . The value of the instruction may change , Or maybe not , But you can ignore unnecessary template updates by comparing the values before and after the update ( See the following for detailed hook function parameters )
componentUpdated: The VNode And its son VNode Call after all updates
unbind: Call it once , Call when an instruction is unbound from an element
Hook function parameters
el: Element bound by instruction , Can be used for direct operation DOM
binding: An object , Contains the following property:
name: Instruction name , barring v- Prefix
value: Binding value of instruction , for example :v-my-directive='1+1' in , Binding value is 2
oldValue: Previous value of instruction binding , Only in update and componentUpdated Available in hook , Available regardless of value change
expression: Instruction expression in string form . for example v-my-directive='1+1' in , Expression for ‘1+1’
arg: Parameters passed to the instruction , Optional . for example v-my-directive: foo in , Parameter is 'foo'
modifiers: An object with modifiers . for example :v-my-directive.foo.bar in , Modifier object is {foo: true, bar: true}
vnode:Vue Compile generated virtual nodes
oldVnode: Previous virtual node , Only in update and componentUpdated Available in hook
<div id="hook-arguments-example" v-demo:foo.a.b="message"></div>
Vue.directive('demo', { bind: function (el, binding, vnode) { var s = JSON.stringify el.innerHTML = 'name: ' + s(binding.name) + '<br>' + 'value: ' + s(binding.value) + '<br>' + 'expression: ' + s(binding.expression) + '<br>' + 'argument: ' + s(binding.arg) + '<br>' + 'modifiers: ' + s(binding.modifiers) + '<br>' + 'vnode keys: ' + Object.keys(vnode).join(', ') } }) new Vue({ el: '#hook-arguments-example', data: { message: 'hello!' } })
The page display effect is as follows
name: 'demo'
value: 'hello!'
expression: 'message'
argument: 'foo'
modifiers: {a: true, b: true}
vnode keys: tag,data,children,text,elm,ns,context...
Dynamic instruction parameters , The parameters of the instruction can be dynamic , for example , stay v-mydirective:[argument]='value' in ,argument Parameters can be updated based on component data , This allows us to use our custom instructions flexibly .
Create a custom instruction , Fix the element at the top of the distance 200px The location of
<div id="test"> <p>Scroll down the page</p> <p v-pin="200"> Distance from top 200px</p> </div>
Vue.directive('pin', { bind: function(el, binding, vnode){ el.style.position = 'fixed' el.style.top = binding.value + 'px' } }) new Vue({ el: '#test' })
When we need to be fixed on the left side instead of at the top , In this case, we need to use dynamic instructions
<div id="test"> <p>Scroll down the page</p> <p v-pin:[direction]="200"> Distance from top 200px</p> </div>
Vue.directive('pin', { bind: function(el, binding, vnode){ el.style.position = 'fixed' let s = binding.arg == 'left' ? 'left' : 'top' el.style[s] = binding.value + 'px' } }) new Vue({ el: '#test' , data(){ return { direction: 'left' } } })
The above custom directive is now flexible enough to support a number of different use cases
Function shorthand
A lot of times , We want to bind and update Trigger the same behavior , And don't care about the other hooks .
Vue.directive('pin', function(el, binding){ el.style.top = binding.value + 'px' })
If the instruction requires more than one value , You can pass in js object , The instruction function can receive all legal js expression
<div v-demo="{ color: 'red', text: 'hello'}"></div>
Vue.directive('demo', function(el, binding){ console.log(binding.value.color) // red console.log(binding.value.text) // hello })
Cases used in projects
Control the buttons on each page through permissions ,
So let's define one directive.js, Write global instructions
import Vue from 'vue'; import store from './store'; Vue.directive('permission', { inserted: (el, binding) => { if (store.getters.userButtons.length) { const buttons = store.getters.userButtons; if (buttons.indexOf(binding.value) < 0) el.parentNode.removeChild(el); } else { store.dispatch('getInfo').then(data => { const { buttons } = data.buttons; if (buttons.indexOf(binding.value) < 0) el.parentNode.removeChild(el); }); } } });
stay main.js Global import in
import './directive.js'
stay vue Used in components , Determine if you have permission to download the button
<el-button round icon="el-icon-document" type="primary" v-permission="'SJML_SQXZ'" @click="applyForDownload" > Download documents </el-button>
6.Vue.filter()
Define filters , Can be used for common text formatting . Filters can be used in two places : Double curly braces interpolate the sum v-bind expression , Filters should be added in js The end of the expression , Indicated by a pipe symbol :'|'
<!-- In double curly braces --> {{ message | capitalize }}
<!-- stay `v-bind` in --> <div v-bind:id="rawId | formatId"></div>
Define local filters in the options of a component
filters: { capitalize: function (value) { if (!value) return '' value = value.toString() return value.charAt(0).toUpperCase() + value.slice(1) } }
Creating Vue Define the filter globally before the instance
Vue.filter('capitalize', function() { if (!value) return '' value = value.toString() return value.charAt(0).toUpperCase() + value.slice(1) }) new Vue({ // ... })
Be careful : When the global filter and the local filter have the same name , Local filters will be used
The filter function always receives the value of the expression as the first parameter
The filter can be connected in series :
{{ message | filterA | filterB }}
In this case ,filterA A filter function that is defined to receive a single parameter , expression message Is passed into the function as an argument . Then proceed to call the filter function, which is also defined to receive a single parameter filterB, take filterA The result is passed on to filterB in .
When filtering js function , Therefore, parameters can be received
{{ message | filterA('arg1', arg2) }}
This example ,filterA The filter function is defined to receive three parameters , among message As the first parameter , Normal string 'arg1' As the second parameter , arg2 As the third parameter
Cases used in projects
So let's define one filters.js
export { formatBoolean, formatDate, formatNum, formatStatus }; // Boolean value function formatBoolean(value) { return value ? " yes " : " no "; } // state function formatStatus(value) { return value ? " success " : " Failure "; } // Timestamp conversion function formatDate(value) { let date = new Date(parseInt(value)); let Y = date.getFullYear(); let M = date.getMonth() + 1 < 10 ? "0" + (date.getMonth() + 1) : date.getMonth() + 1; // let D = date.getDate(); let D = date.getDate() < 10 ? "0" + date.getDate() : date.getDate(); let h = date.getHours() < 10 ? "0" + date.getHours() : date.getHours(); let m = date.getMinutes() < 10 ? "0" + date.getMinutes() : date.getMinutes(); let s = date.getSeconds() < 10 ? "0" + date.getSeconds() : date.getSeconds(); return Y + "." + M + "." + D + " " + h + ":" + m + ":" + s; } // Number plus comma function formatNum(num) { num = (num || 0).toString(); let result = ""; while (num.length > 3) { result = "," + num.slice(-3) + result; num = num.slice(0, num.length - 3); } if (num) { result = num + result; } return result; }
And then in main.js The global introduction of
import * as filters from './filters.js' Object.keys(filters).forEach(item => { Vue.filter(item, filters[item]) })
// So let's talk about that Object.keys() Method , An array of strings representing all enumerable properties of a given object let zn = {name: 'zhangning', age: '24', height: '187'} Object.keys(zn);// ['name', 'age', 'height'] Returns an array of enumerable properties // Handling arrays , Returns an array of index values let arr = [100, 200, 300, 400, 500] Object.keys(arr);// ['0', '1', '2', '3', '4'] Returns an array of index value strings // Processing strings , Returns an array of index values let str = 'zhang'; Object.keys(str);// ['0', '1', '2', '3', '4'] // Common skills let zn = {name: 'zhangning', age: '25', address: ' Hefei ', getName: function()} Object.keys(person).map(item => { person[item] // Get the corresponding value of the attribute , Do something about it })
7.Vue.component()
// Define a name button-counter The new component Vue.component('button-counter', { data: function () { return { count: 0 } }, template: '<button v-on:click="count++">You clicked me {{ count }} times.</button>' })
data It has to be a function , Therefore, each instance can maintain an independent copy of the returned object , If it's not a function , It will affect all instances of the component
Custom global component case in project
First create a component download.vue
And then create a download.js, stay js Introduced components in
// Import components import DLFLoading from './index.vue'; // Custom component object const DownloadDialog = { // install It's the default way . When the outside world is use When this component , It will call itself install Method , Pass on one at a time Vue The parameters of this class install: function(Vue) { // Vue.component() Same usage as normal global registration components , It can be understood as passing through install and Vue.use() Function registers global components Vue.component('DownloadDialog', DLFLoading); } } // export export default DownloadDialog;
And then main.js Introduce components globally in
// Global introduction of custom downloads loading import DownloadDialog from '@/components/DownloadDialog/download.js'; Vue.use(DownloadDialog);
Finally, it can be used directly in the project
<DownloadDialog @cancelDownload="cancelDownload" :downloadOver="downloadOver" :downloadLoading="downloadLoading" ></DownloadDialog>
8.Vue.use()
install Vue.js plug-in unit . If the plug-in is an object , You must provide install Method . If the plug-in is a function , It will be used as install Method .install Method call , Will Vue Pass in as a parameter .
The method needs to be new Vue() Called before
When install Method is called multiple times by the same plug-in , The plug-in will only be installed once .
Plugins are usually used for Vue Add global features . There are no strict limits to the functional scope of plug-ins There are generally the following kinds
1. Add a global method or property
2. Add global resources : Instructions / filter / Transition, etc
3. Add some component options through global blending
4. add to Vue Example method , By adding them to Vue.prototype Implemented on
5. A library , Provide your own api, It also provides one or more of the functions mentioned above
The use of plug-in
Through a global approach Vue.use() The use of plug-in . It needs to be called new Vue() Complete before starting the app
// call MyPlugin.install(Vue) Vue.use(MyPlugin) new Vue({ // ... Component options })
You can also pass in an optional option object
Vue.use(MyPlugin, {someOption: true})
Vue.use Will automatically prevent multiple registrations of the same plug-in , The plug-in is registered only once even if it is called multiple times
9.Vue.mixin()
Global registration of a hybrid , Affects every... Created after registration Vue example . Plug in authors can use mash in , Inject custom behavior into components ( The official does not recommend the use of )
Official website global mixed case . The global registration can also be performed by blending , Use with extreme care , Once global blending is used , It will affect every subsequent creation of Vue example . When used properly , It can be used to customize option injection processing logic .
// Options for customization myOption Inject a processor
Vue.mixin({ created: function(){ var myOption = this.$options.myOption if(myOption) { console.log(myOption) } } }) new Vue({ myOption: 'zhangning' }) // => 'zhangning'
Be careful : Use global mashup carefully , Because it affects every single created Vue example ( Include third party components ). Most of the time , This should be applied to custom options , Just like the example above , It is recommended to publish it as a plug-in , In order to avoid repeated applications mixed with
Use cases
Define a mixin.js
let MiXin = { data(){ return { name: 'zhangning' } }, created(){ console.log(' This is a mixin Medium name', this.name) }, mounted(){}, methods: {} } export default MiXin
// Introduced the global import mixin from './mixin' Vue.mixin(mixin) // stay vue Local introduction of import '@/mixin' export default { mixins: [mixin] }
Considerations for mixing and merging components
1. Data objects data Recursively merge internally , In case of conflict with component data, component data takes precedence
2. Hook function with the same name (created,mounted) Will be mixed into an array , Will be called . In addition, the hook of the object will be called before the component itself hooks
3. Option with value as object (methods,components,directives) Will be mixed into the same object , When two object key names conflict , Remove the key value pairs of component objects
10.Vue.compile() -- Template rendering
Compile a template string into render function . Designed to be available in full version
let res = Vue.compile('<div><span>{{ massage }}</span></div>')
new Vue({
data: {
message: 'hello'
},
render: res.render,
staticRenderFns: res.staticRenderFns
})
The above is a small example given by the official website .
After further understanding , Come back and update
11.Vue.observable() -- It can be used to share data between components
Make an object responsive ,Vue It will be used internally to deal with data The object returned by the .
The returned object can be used directly in the rendering function and calculation properties , And will launch the corresponding update when changes occur .
Dealing with the simple problem of sharing data state across components , It can be said that it is a simplified vuex
Example
establish store.js
import Vue from 'vue' export const store = Vue.observable({num: 0}) export const mutations = { setNum (num) { store.num = num } }
Use in components ( All of the explanations are without examples , Understand faster )
<template> <div> <span> Select quantity </span> <button @click="setNum(num + 1)"> + </button> <span>count</span> <button @click="setNum(num - 1)"> - </button> </div> </template> <script> import { store, mutations } from '@/store/store' export default { name: 'numIndex', computed: { count() { return store.num } }, methods: { setNum: mutations.setNum } } </script>
12.Vue.version()
Provide string form of Vue Installation version number . This is very useful for plug-ins and components in the community , You can take different strategies depending on the version number
let version = Number(Vue.version.split('.')[0])
if (version == 2) {
} else if (version == 1) {
} else {}
Is to get the currently used vue Version number , The principle is to read package.json Medium version Field
That's all vue API overall situation API All of ,
Bao jianfeng from the sharpen out , Plum blossom fragrance from the bitter cold .