目录
1.Vue.directive
参数有三个:
el:指令所绑定的元素,可以用来直接操作dom
binding:一个对象,包含指令的很多信息
vnode: Vue编译生成的虚拟节点
demo1:自动获取焦点
<div id="app">
<input type="text" v-focus/>
</div>
// 注册一个全局自定义指令 v-focus
Vue.directive('focus', {
// 当绑定元素插入到 DOM 中。
inserted: function (el,binding) {
// 聚焦元素
el.focus();
}
});
// 挂载
new Vue({
el:'#app'
});
demo2:拖拽
1.被拖拽的元素必须用position定位,才能被拖动;
2.自定义指令完成后需要实例化Vue,挂载元素;
3.inserted
: 被绑定元素插入父节点时调用(父节点存在即可调用,不必存在于 document 中)。
<style type="text/css">
.one,.two{
height:100px;
width:100px;
border:1px solid #000;
position: absolute;
-webkit-user-select: none;
-ms-user-select: none;
-moz-user-select: -moz-none;
cursor: pointer;
}
.two{
left:200px;
}
</style>
<div id="app">
<div class="one" v-drag>拖拽one</div>
<div class="two" v-drag>拖拽two</div>
</div>
<script>
// 注册一个全局自定义指令drag
Vue.directive('drag', {
// 将事件插入到dom中
inserted:function(el){
// 绑定鼠标事件
el.οnmοusedοwn=function(e){
let l=e.clientX-el.offsetLeft;
let t=e.clientY-el.offsetTop;
document.οnmοusemοve=function(e){
el.style.left=e.clientX-l+'px';
el.style.top=e.clientY-t+'px';
};
el.οnmοuseup=function(){
document.οnmοusemοve=null;
el.οnmοuseup=null;
}
}
}
})
// 挂载,绑定到dom
new Vue({
el:'#app'
});
</script>
2.Vue.use
参数:插件
安装 Vue.js 插件。如果插件是一个对象,必须提供 install 方法。如果插件是一个函数,它会被作为 install 方法。install 方法调用时,会将 Vue 作为参数传入。
该方法需要在调用 new Vue() 之前被调用。
当 install 方法被同一个插件多次调用,插件将只会被安装一次。
// 一般写在main.js中
Vue.use(animate);
window.vm = new Vue({
render: h => h(App),
}).$mount('#app');
3.Vue.extend
参数:组件对象
应用场景:
在 vue 项目中,初始化的根实例后,所有页面基本上都是通过 router 来管理,组件也是通过 import 来进行局部注册,所以组件的创建不需要去关注,相比 extend 要更省心一点点。
但是这样做会有几个缺点:
1.组件模板都是事先定义好的,如果我要从接口动态渲染组件怎么办?
2.所有内容都是在 #app 下渲染,注册组件都是在当前位置渲染。如果我要实现一个类似于 window.alert() 提示组件要求像调用 JS 函数一样调用它,该怎么办?
这时候,Vue.extend + vm.$mount 组合就派上用场了。注意:extend 创建的是 Vue 构造器,而不是我们平时常写的组件实例,所以不可以通过 new Vue({ components: testExtend }) 来直接使用,需要通过 new Profile().$mount(’#mount-point’) 来挂载到指定的元素上。
<div id="mount-point"></div>
// 创建构造器
var Profile = Vue.extend({
template: '<p>{{firstName}} {{lastName}} aka {{alias}}</p>',
data: function () {
return {
firstName: 'Walter',
lastName: 'White',
alias: 'Heisenberg'
}
}
})
// 创建 Profile 实例,并挂载到一个元素上。
new Profile().$mount('#mount-point')
4.Vue.set
参数有三个:
参数1: 目标对象
参数2: 属性名
参数3: 属性值
应用场景:
因为受现代JS的限制,vue不能检测到对象属性的添加或删除。
由于vue会在初始化实例时对属性执行 getter/setter 转化过程,所以属性必须在data对象上存在才能让vue转换它,这样它才能是响应的。vue不允许在已经创建的实例上动态添加新的根级响应式属性,不过可以使用Vue.set()方法将响应式属性添加到嵌套的对象上。
let vm = new Vue({
el:"#app",
data:{
json:{
username:"张三",
age:20
},
msg:"hello"
}
})
//vm.json.username = "李四" 修改属性可以
/* 如果对之前存在的属性username,age进行更改是可以的,
因为内部通过Object.defineProperty实现了数据双向绑定,
但是对与后续新增添的属性例如sex,那么视图是没有办法渲染的 */
vm.json["sex"]="男" //发现页面不会渲染sex这个属性
// 所以需要用到Vue.set()
Vue.set(vm.json, "sex", "女")
5.Vue.mixin
参数:混入对象
mixin是一种类,在vue中就是js文件,主要的作用是作为功能模块引用。因为在项目中,可能不同组件会有相同的功能,比如控制元素的显示和隐藏,如果他们的变量和规则也完全相同的话,就可以把这个功能单独提取出来,放在mixin.js中再引入,就可以实现一样的功能了,这样大大提高了代码复用性。局部混入就是在每个组件中引入,全局混入就是在main.js中通过Vue.mixin()引入。
首先我们在src目录下新建一个名为mixin的文件夹,并在mixin文件中创建一个mixin.js文件:
//抛出混入对象,方便外部访问
export const mixin={
data(){
return {
number:1
}
}
}
然后我们新建一个page1.vue组件,并将mixin.js引入进来
<template>
//这里读的值其实是mixin的值,因为这个时候mixin已经混入到vue实例中了
<div>page1的值是:{{number}}</div>
</template>
<script>
//引入mixin.js
import {mixin} from "./mixin/mixin"
export default {
//这里注意:属性名为mixins,值为数组类型
mixins:[mixin],
data () {
return {
}
},
}
</script>
<style scoped>
</style>
通过修改组件,我们可以知道mixin混入对象的变量是不会共享的,也就是你vue组件发生了变化,并不会通知mixin进行实时刷新数据,发生的变化只会在当前vue组件中生效,不影响其他组件。
6.Vue.filter
参数有两个:
参数1:字符串的id
参数2:定义函数
注册或获取全局过滤器。
// 注册
Vue.filter('my-filter', function (value) {
// 返回处理后的值
})
// getter,返回已注册的过滤器
var myFilter = Vue.filter('my-filter')
7.Vue.component
参数有两个:
参数1:字符串的id,组件标签名
参数2:定义函数,构造器对象
demo1:不在脚手架中注册
// 1、创建全局组件构造器
const cpn1=Vue.extend({
template:`
<div>
<h2>我是标题2</h2>
<p>我是内容,呵呵呵呵呵呵呵</p>
</div>
`
});
//2、注册全局组件
Vue.component('cpn',cpn1);
/*===================等价于======================*/
Vue.component('cpn1',{
template:`
<div>
<h2>我是标题1</h2>
<p>我是内容,呵呵呵呵呵呵呵</p>
</div>
`
});
demo2:template写法
<template id="cpn">
<!--子组件很多标签,必须有个根节点-->
<div>
<h2>我是标题</h2>
<p>我是内容,呵呵呵呵呵呵呵呵呵呵呵呵呵</p>
</div>
</template>
<script>
//全局组件
Vue.component('cpn',{
template:'#cpn'
});
</script>
demo3:脚手架中注册
// 1.在components文件夹下新建组件
export default {
name: "TypeNav" // 注意:必须要有name,也就是组件名
}
// 2.在main.js中引入全局组件并注册
import TypeNav from '@/components/TypeNav'
//第一个参数:全局组件的名字。第二个参数:哪个组件
Vue.component(TypeNav.name,TypeNav);
8.Vue.delete
参数有两个:
参数1: 要修改的对象名/数组名,不能是一个 Vue 实例或 Vue 实例的根数据对象
参数2: 要删除的属性名/数组元素索引
Vue.js
源码中,Vue.delete
和vm.$delete
指向的是同一个函数,两者作用完全相同,其中,vm.$delete
是Vue.delete
的别名。
export default() {
data() {
food: {
name: 'apple'
}
}
}
Vue.$delete(food, 'name');
9.Vue.nextTick
在下次 DOM 更新循环结束之后执行延迟回调。在修改数据之后立即使用这个方法,获取更新后的 DOM。简单的理解是:当数据更新了,在dom中渲染后,自动执行该函数。
<template>
<div class="hello">
<div>
<button id="firstBtn" @click="testClick()" ref="aa">{{testMsg}}</button>
</div>
</div>
</template>
<script>
export default {
name: 'HelloWorld',
data () {
return {
testMsg:"原始值",
}
},
methods:{
testClick:function(){
let that=this;
that.testMsg="修改后的值";
console.log(that.$refs.aa.innerText); //that.$refs.aa获取指定DOM,输出:原始值
}
}
}
</script>
// 使用this.$nextTick
methods:{
testClick:function(){
let that=this;
that.testMsg="修改后的值";
that.$nextTick(function(){
console.log(that.$refs.aa.innerText); //输出:修改后的值
});
}
}
什么时候需要用nextTick?
1. Vue生命周期的created()钩子函数进行的DOM操作,一定要放在Vue.nextTick()的回调函数中,原因是在created()钩子函数执行的时候DOM 其实并未进行任何渲染,而此时进行DOM操作无异于徒劳,所以此处一定要将DOM操作的js代码放进Vue.nextTick()的回调函数中。与之对应的就是mounted钩子函数,因为该钩子函数执行时所有的DOM挂载已完成。
created(){
let that=this;
that.$nextTick(function(){ //不使用this.$nextTick()方法会报错
that.$refs.aa.innerHTML="created中更改了按钮内容"; //写入到DOM元素
});
},
2.当项目中你想在改变DOM元素的数据后基于新的dom做点什么,对新DOM一系列的js操作都需要放进Vue.nextTick()的回调函数中;通俗的理解是:更改数据后当你想立即使用js操作新的视图的时候需要使用它。
<template>
<div class="hello">
<h3 id="h">{{testMsg}}</h3>
</div>
</template>
<script>
export default {
name: 'HelloWorld',
data () {
return {
testMsg:"原始值",
}
},
methods:{
changeTxt:function(){
let that=this;
that.testMsg="修改后的文本值"; //vue数据改变,改变dom结构
let domTxt=document.getElementById('h').innerText;
console.log(domTxt); //输出可以看到vue数据修改后DOM并没有立即更新
if(domTxt==="原始值"){
console.log("文本data被修改后dom内容没立即更新");
}else {
console.log("文本data被修改后dom内容被马上更新了");
}
}
}
}
</script>
正确的用法是:vue改变dom元素结构后使用vue.$nextTick()方法来实现dom数据更新后延迟执行后续代码
changeTxt:function(){
let that=this;
that.testMsg="修改后的文本值"; //修改dom结构
that.$nextTick(function(){ //使用vue.$nextTick()方法可以dom数据更新后延迟执行
let domTxt=document.getElementById('h').innerText;
console.log(domTxt); //输出可以看到vue数据修改后并没有DOM没有立即更新,
if(domTxt==="原始值"){
console.log("文本data被修改后dom内容没立即更新");
}else {
console.log("文本data被修改后dom内容被马上更新了");
}
});
},
Vue.nextTick(callback) 使用原理:
Vue是异步执行dom更新的,一旦观察到数据变化,Vue就会开启一个队列,然后把在同一个事件循环 (event loop) 当中观察到数据变化的 watcher 推送进这个队列。
如果这个watcher被触发多次,只会被推送到队列一次。这种缓冲行为可以有效的去掉重复数据造成的不必要的计算和DOm操作。而在下一个事件循环时,Vue会清空队列,并进行必要的DOM更新。
当你设置 vm.someData = 'new value',DOM 并不会马上更新,而是在异步队列被清除,也就是下一个事件循环开始时执行更新时才会进行必要的DOM更新。如果此时你想要根据更新的 DOM 状态去做某些事情,就会出现问题。
为了在数据变化之后等待 Vue 完成更新 DOM ,可以在数据变化之后立即使用 Vue.nextTick(callback) 。这样回调函数在 DOM 更新完成后就会调用。
10.Vue.compile
参数:
{string} template
Vue
的核心可以分为三个大块:数据处理和双向绑定、模板编译、虚拟dom。compile是编译
var res = Vue.compile('<div><span>{{ msg }}</span></div>')
new Vue({
data: {
msg: 'hello'
},
render: res.render,
staticRenderFns: res.staticRenderFns
})
在 render 函数中编译模板字符串,注意:只在独立构建时有效
11.Vue.observable
可以理解为一个精简版的vuex,用于状态管理
// /store/store.js
import Vue from 'vue'
export const store = Vue.observable({ count: 0 })
export const mutations = {
setCount (count) {
store.count = count
}
}
<template>
<div>
<label for="bookNum">数 量</label>
<button @click="setCount(count+1)">+</button>
<span>{{count}}</span>
<button @click="setCount(count-1)">-</button>
</div>
</template>
<script>
import { store, mutations } from '../store/store' // Vue2.6新增API Observable
export default {
name: 'Add',
computed: {
count () {
return store.count
}
},
methods: {
setCount: mutations.setCount
}
}
</script>
12.Vue.version
用于查看版本号