文章目录
- 『 总览 』
- 『 Vue.extend 』
- 『 Vueponent 』
- 『 Vue.nextTick 』
- 『 Vue.set 』
- 『 Vue.delete 』
- 『 Vue.directive 』
- 『 Vue.filter 』
- 『 Vue.use 』
- 『 Vue.mixin 』
- 『 Vuepile』
- 『 Vue.version 』
『 总览 』
Vue.extend(options) // 返回一个子类构造函数,也就是预设部分选项的vue实例构造器
Vue.component(id, [definition]) // 注册或获取全局组件
Vue.nextTick([callback, context]) // 在下次 DOM 更新循环结束之后执行延迟回调
Vue.set(target, key, value) // 设置对象的属性,如果是响应式对象,将会触发视图更新
Vue.delete(target, key) // 删除对象的属性,如果是响应式对象,将会触发视图更新
Vue.directive(id, [definition]) // 注册或获取全局指令
Vue.filter(id, [definition]) // 注册或获取全局过滤器
Vue.use(plugin) // 安装 Vue 插件
Vue.mixin(mixin) // 全局注册一个 mixin 对象
Vue.compile(template) // 在 render 函数中编译模板字符串
Vue.version // 提供当前使用 Vue 的版本号
『 Vue.extend 』
实际业务开发中我们很少使用,因为它返回的是组件构造函数,而不是我们平时常写的组件实例,所以不可以通过 new Vue({ components: 组件名 }) 来直接使用,比常用的 Vueponent 写法要更加繁琐一些,对比 Vueponent,更适用于不需要使用组件名称来进行注册和使用的组件
使用场景:独立组件开发(Vue.extend + $mount),例如实现通知弹窗组件
// 使用
this.$notice(Notice, {
title: '通知弹窗组件',
message: '提示信息',
duration: 1000
}).show();
// create 方法
import Vue from "vue";
// 创建它的实例,并且将他挂载到 body 上
// 返回组件实例
function create(Component, props) {
// 1. Vue.extend(options) 方式
const Ctor = Vue.extend(Component);
const comp = new Ctor({propsData: props}); // 创建组件实例
comp.$mount(); // 不指定宿主元素,则会创建真实 DOM,但是不会追加操作
document.body.appendChild(comp.$el); // 将真实 DOM 挂载到 body 上
comp.remove = () => {
document.body.removeChild(comp.$el); // 移除 DOM
comp.$destroy(); // 销毁组件
};
// 2. render 方式
// const vm = new Vue({
// render(h) {
// // h 是 createElement,返回 VNode,是虚拟 DOM
// // 需要挂载才能变成真是 DOM
// return h(Component, { props });
// }
// }).$mount(); // 本质上将vdom => dom,不指定宿主元素,则会创建真实 DOM,但是不会追加操作。如果指定宿主元素,则会直接覆盖
// document.body.appendChild(vm.$el); // 获取真实 DOM
// const comp = vm.$children[0]; // 给组件实例添加销毁⽅法
// comp.remove = () => { // 删除
// document.body.removeChild(vm.$el);
// vm.$destroy();
// };
return comp;
}
// 暴露调⽤接⼝
export default create;
// Notice.vue 通知组件
<template>
<div class="box" v-if="isShow">
<h3>{{title}}</h3>
<p class="box-content">{{message}}</p>
</div>
</template>
<script>
export default {
props: {
title: {
type: String,
default: ""
},
message: {
type: String,
default: ""
},
duration: {
type: Number,
default: 1000
}
},
data() {
return {
isShow: false
};
},
methods: {
show() {
this.isShow = true;
setTimeout(this.hide, this.duration);
},
hide() {
this.isShow = false;
this.remove();
}
}
};
</script>
<style>
.box {
position: fixed;
width: 100%;
top: 16px;
left: 0;
text-align: center;
pointer-events: none;
background-color: #fff;
border: grey 3px solid;
box-sizing: border-box;
}
.box-content {
width: 200px;
margin: 10px auto;
font-size: 14px;
padding: 8px 16px;
background: #fff;
border-radius: 3px;
margin-bottom: 8px;
}
</style>
// 使⽤插件进⼀步封装便于使⽤,create.js
import Notice from '@/components/Notice.vue'
//...
export default {
install(Vue) {
Vue.prototype.$notice = function (options) {
return create(Notice, options)
}
}
}
『 Vueponent 』
全局注册的行为必须在根 Vue 实例 (通过 new Vue) 创建之前发生,内部实质上调用了 Vue.extend
<div id="app">
<div>#app</div>
<my-header></my-header>
<my-main></my-main>
<my-footer></my-footer>
</div>
<div id="root">
<div>#root</div>
<my-header></my-header>
<my-main></my-main>
<my-footer></my-footer>
</div>
<script type="text/javascript" src="./vue.js"</script>
<script>
// 定义组件
const Header = {
template: '<header>全局头部组件</header>'
};
const Main = {
template: '<main>局部主体组件</main>'
};
const Footer = {
template: '<footer>全局尾部组件</footer>'
};
// 全局注册组件
// Vueponent('组件名'[, 组件的配置对象])
Vue.component('my-header', Header);
Vue.component('my-footer', Footer);
// 第一个实例
new Vue({
el: '#app',
// 局部注册组件——内容
components: {
'my-main': Main
}
});
// 第二个实例
new Vue({
el: '#root',
})
</script>
页面运行结果
#app
全局头部组件
局部主体组件
全局尾部组件
#root
全局头部组件
全局尾部组件
控制台运行结果
[Vue warn]: Unknown custom element: <my-main> - did you register the component correctly? For recursive components, make sure to provide the "name" option.
(found in <Root>)
会报错:没有注册局部主体组件
『 Vue.nextTick 』
下面了解下 nextTick 的主要应用的场景及原因
-
在Vue生命周期的 created() 钩子函数进行的 DOM 操作一定要放在 Vue.nextTick() 的回调函数中
-
在 created() 钩子函数执行的时候 DOM 其实并未进行任何渲染,而此时进行 DOM 操作无异于徒劳,所以此处一定要将 DOM 操作的 js 代码放进 Vue.nextTick() 的回调函数中
-
在数据变化后要执行的某个操作,而这个操作需要使用随数据改变而改变的 DOM 结构的时候,这个操作都应该放进 Vue.nextTick() 的回调函数中
<div class="app">
<div ref="msgDiv">{{msg}}</div>
<div v-if="msg1">Message got outside $nextTick: {{msg1}}</div>
<div v-if="msg2">Message got inside $nextTick: {{msg2}}</div>
<div v-if="msg3">Message got outside $nextTick: {{msg3}}</div>
<button @click="changeMsg">
Change the Message
</button>
</div>
new Vue({
el: '.app',
data: {
msg: 'Hello Vue.',
msg1: '',
msg2: '',
msg3: ''
},
methods: {
changeMsg() {
this.msg = "Hello world."
this.msg1 = this.$refs.msgDiv.innerHTML
/**
* Vue.nextTick(options)
* 用于延迟执行一段代码
* 接受2个参数(回调函数和执行回调函数的上下文环境)
* 如果没有提供回调函数,那么将返回 promise 对象
*/
this.$nextTick(() => {
this.msg2 = this.$refs.msgDiv.innerHTML
})
this.msg3 = this.$refs.msgDiv.innerHTML
}
}
})
『 Vue.set 』
Vue.set(target, key, value)
- target: 要更改的数据源(可以是对象或者数组)
- key: 要修改的变量
- value: 重新赋的值
如果在实例创建之后添加新的属性到实例上,它不会触发视图更新。当你把一个普通的 js 对象传入 Vue 实例作为 data 选项,Vue 将遍历此对象所有的属性,并使用 Object.defineProperty 把这些属性全部转为 getter/setter。
受现代 js 的限制 (以及废弃 Object.observe),Vue 不能检测到对象属性的添加或删除。由于 Vue 会在初始化实例时对属性执行 getter/setter 转化过程,所以属性必须在 data 对象上存在才能让 Vue 转换它,这样才能让它是响应的。
Vue 不允许在已经创建的实例上动态添加新的根级响应式属性 (root-level reactive property)。然而它可以使用 Vue.set(object, key, value) 方法将响应属性添加到嵌套的对象上。
『 Vue.delete 』
Vue.delete(target, key)
- target: 要更改的数据源(可以是对象或者数组)
- key: 要删除的变量
删除对象的属性,如果对象是响应式的,确保删除能触发更新视图,这个方法主要用于避开 Vue 不能检测到属性被删除的限制
『 Vue.directive 』
Vue 允许注册自定义指令,用于对底层 DOM 进行操作
// Vue.directive(id[, definition])
Vue.directive("focus", {
/**
* 下列钩子函数拥有如下参数
* el -> 指令绑定的 HTML 元素,可以用来直接操作 DOM
* vnode -> Vue编译生成的虚拟节点
* oldVnode -> 之前的虚拟节点,仅在 update、componentUpdated 钩子中可用
* binding -> 一个对象,包含以下属性:
* * name -> 指令名称,不包括 v- 前缀
* * value -> 指令的绑定值,例如 v-my-directive="1 + 1" 中 value 的值是2
* * oldValue -> 指令绑定的之前一个值,仅在 update、componentUpdated 钩子中可用
* * expression -> 绑定值的字符串形式,例如 v-my-directive="1 + 1" 当中 expression 的值为"1 + 1"
* * arg -> 传给指令的参数,例如 v-my-directive:foo中arg 的值是 "foo"
* * modifiers -> 包含修饰符的对象,例如 v-my-directive.foo.bar 的 modifiers 的值是 {foo: true, bar: true}
*/
bind() {
// 指令第一次绑定到元素时调用,只会调用一次,可以用来执行一些初始化操作。
},
inserted(el) {
// 被绑定元素插入父节点时调用。
},
update() {
// 所在组件的VNode更新时调用,但是可能发生在其子VNode更新之前。
},
componentUpdated() {
// 所在组件VNode及其子VNode全部更新时调用。
},
unbind() {
// 指令与元素解绑时调用,只会被调用一次。
}
})
// btnPermisstion.js
import store from '@/store/index'
export default {
install (Vue) {
Vue.directive('has', {
bind (el, binding) {
const permissionCode = binding.value
const permissionList = store.getters.btnPermissions
if (permissionList.indexOf(permissionCode) === -1) {
Vue.prototype.$nextTick(() => {
el.parentNode.removeChild(el)
})
}
}
})
}
}
// main.js
import btnsPermission from './directive/btnPermisstion'
......
Vue.use(btnsPermission)
『 Vue.filter 』
Vue 可以通过定义过滤器,进行一些常见的文本格式化,可以用于 mustache 插值和 v-bind 表达式当中,使用时通过管道符 | 添加在表达式尾部,和计算属性的区别在于不用依赖 data 当中的属性
// filters.js
const numUnitConversion = value => {
return value >= 10000 ? (value / 10000).toFixed(1) : value
}
const stubValue = value => {
if (!value) {
return '-'
} else {
return value
}
}
export {
stubValue,
numUnitConversion
}
// main.js
import * as filters from './common/filters'
// 全局过滤器设置
Object.keys(filters).forEach(key => {
// Vue.filter(id[, definition])
Vue.filter(key, filters[key])
})
直接用过滤管道符 | 连接需要过滤的数据和定义配置的过滤函数即可
<div class="info_tit info_last">
<span>磁盘总量</span>
<span><i class="color_6">{{ rectangleData.diskNum | stubValue }}</i> TB</span>
</div>
『 Vue.use 』
Vue 通过插件来拓展一些全局功能,Vue 插件都会覆写其 install() 方法,该方法第1个参数是 Vue 构造器, 第2个参数是可选的 option 对象
Vue 首先判断这个插件是否被注册过,不允许重复注册
如果我们传入一个包含 install 方法的对象,那么我们就调用这个 install 方法并将整理好的数组当成参数传入 install 方法中
如果我们传入一个函数,那么我们就直接调用这个函数并将整理好的数组当成参数传入
之后给这个插件添加至已经添加过的插件数组中,表示已经注册过,最后返回 Vue 对象
MyPlugin.install = function (Vue, options) {
// 添加全局方法或属性
Vue.myGlobalMethod = function () {}
// 添加全局资源
Vue.directive("my-directive", {
bind (el, binding, vnode, oldVnode) {}
})
// 注入组件
Vue.mixin({
created: function () {}
})
// 添加实例方法
Vue.prototype.$myMethod = function (methodOptions) {}
}
// Vue.use(plugin[, options])
Vue.use(MyPlugin, {someOption: true})
vue-router 等插件检测到 Vue 是全局对象时会自动调用 Vue.use() ,如果在 CommonJS 模块环境中,则需要显式调用 Vue.use()
『 Vue.mixin 』
使用全局 mixins 将会影响到所有之后创建的 Vue 实例,如果我们并不想给每一个组件实例都混入这些配置 options,而只是个别的组件,最好不要使用 mixin,它可能会影响到我们组件的性能。
// *.vue
<template>
<div id="box">
<nav-header ref="navHeader" title="AI-fisher" :styleObject="navHeaderStyle" :shareParams="shareParams"></nav-header>
......
<cube-scroll :options="options" :listenScroll="true" @scroll="scrolling" ref="scroll">
......
</cube-scroll>
......
</div>
</template>
// main.js
Vue.mixin({
data () {
return {
navHeaderStyle: {
opacity: 0
}
}
},
methods: {
scrolling(a) {
let num = ~Math.floor(a.y) > 0 ? ~Math.floor(a.y) > 128 ? 128 : ~Math.floor(a.y) : 0
this.navHeaderStyle.opacity = num / 128
}
}
})
『 Vuepile』
在 render 函数中编译模板字符串。只在独立构建时有效
// Vuepile(template)
const res = Vue.compile('<div><span>{{ msg }}</span></div>')
new Vue({
data: {
msg: 'hello'
},
render: res.render,
staticRenderFns: res.staticRenderFns
})
『 Vue.version 』
获取当前使用的 Vue 版本号,在我们去寻找安装的一些依赖包的时候,需要知道支持的 Vue 版本是什么,所以这个时候就会用到这个方法,其原理就是读取 package.json 中的 version 字段
更多推荐
使用 Vue 实例( 全局 API )
发布评论