Vue.prototype详解及使用方式

 更新时间:2024年03月24日 09:16:07   作者:sslcsq  
这篇文章主要介绍了Vue.prototype详解及使用方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教

我们可能会在很多组件里用到数据/实用工具,但是不想污染全局作用域。

这种情况下,可以通过在原型上定义它们使其在每个 Vue 的实例中可用。

1. 基本示例

在main.js中添加一个变量到 Vue.prototype

Vue.prototype.$appName = 'My App'

这样 $appName 就在所有的 Vue 实例中可用了,甚至在实例被创建之前就可以

 beforeCreate: function () {
    console.log(this.$appName)
 }

控制台会打印出 My App

2. 为实例prototype设置作用域

为什么 appName 要以 $ 开头?

$ 是在 Vue 所有实例中都可用的 property 的一个简单约定

这样做会避免和已被定义的数据、方法、计算属性产生冲突。

如果我们设置:

Vue.prototype.appName = 'My App'
export default {
  data(){
    return{
      appName:'组件实例中的appName'
    }
  },
  beforeCreate: function () {
    console.log(this.appName)
  },
  created: function () {
    console.log(this.appName)
  },
}
</script>

日志中会先出现 “My App”,然后出现 “组件实例中的appName”,因为 this.appName 在实例被创建之后被 data 覆写了。

我们通过 $ 为实例 property 设置作用域来避免这种事情发生。

3. 注册和使用全局变量

每个组件都是一个vue实例,Vue.prototype加一个变量,只是给每个组件加了一个属性,这个属性的值并不具有全局性。

比如以下例子:

Vue.prototype.$appName = 'main'

给所有组件注册了一个属性 $appName,赋予初始值 'main' ,所有组件都可以用 this.$appName 访问此变量;

如果组件中没有赋值,初始值都是'main'

app.vue

<template>
  <div id="app">
    主组件name-》{{this.$appName}}
    <p>{{newName}}</p>
    <button @click="changeName">更改name</button>
    <button @click="$router.push('/cs')">跳转</button>
    <hr>
    <router-view></router-view>
  </div>
</template>
<script>
export default {
  data(){
    return{
      newName:''
    }
  },
  methods:{
    changeName(){
      this.$appName = "changeName"
      this.newName=this.$appName
    }
  }
}
</script>

ce.vue

<template>
  <div class="ce">
    跳转页面name-》{{this.$appName}}
  </div>
</template>

在app.vue中点击更改name,$appName值已发生改变,但cs.vue页面的值没有发生变化

如果要实现全局变量的功能,需要把属性变为引用类型

Vue.prototype.$appName = { name: 'main' }

使用 this.$appName.name 改变和引用相应的值

app.vue

<template>
  <div id="app">
    主组件name-》{{this.$appName.name}}
    <p>{{newName}}</p>
    <button @click="changeName">更改name</button>
    <button @click="$router.push('/cs')">跳转</button>
    <hr>
    <router-view></router-view>
  </div>
</template>
<script>
export default {
  data(){
    return{
      newName:''
    }
  },
  methods:{
    changeName(){
      this.$appName.name = "changeName"
      this.newName=this.$appName.name
    }
  }
}
</script>

cs.vue

<template>
  <div class="ce">
    跳转页面name-》{{this.$appName.name}}
  </div>
</template>

在app.vue中点击更改name,$appName值已发生改变,cs.vue页面的值也发生了变化

4. 原型方法的上下文

在 JavaScript 中一个原型的方法会获得该实例的上下文,也就是说可以使用 this 访问:数据、计算属性、方法或其它任何定义在实例上的东西。

让我们将其用在一个名为 $reverseText 的方法上:

// main.js
Vue.prototype.$reverseText = function (propertyName) {
  this[propertyName] = this[propertyName]
    .split('')
    .reverse()
    .join('')
}
<script>
export default {
  data() {
    return{
      message: 'Hello'
    }
  },
  created() {
    console.log(this.message) // => "Hello"
    this.$reverseText('message')
    console.log(this.message) // => "olleH"
  }
}
</script>

5. 应用示例

引入bus

const bus = new Vue()
Vue.prototype.$bus = bus
this.$bus.$emit("fun",'A组件传来的值')

axios…

6.Vue.prototype中的api

Vue.prototype是Vue.js框架中一个重要的原型对象,通过它可以在全局范围内定义和共享Vue实例方法、指令、过滤器等。

在Vue.prototype对象上定义的属性和方法,会被挂载到所有Vue实例的原型链上,从而可以在组件中通过this访问。

一些常见的Vue.prototype中的API包括:

  • $emit(eventName[, ...args]):触发当前实例上的事件。可以通过该方法向父组件或同级组件传递数据。
  • $on(eventName, callback):监听当前实例上的事件。可以通过该方法在组件间传递数据。
  • $nextTick(callback):在下次 DOM 更新循环结束之后执行延迟回调。常用于更新后立即操作 DOM。
  • $watch(exprOrFn, callback[, options]):监听一个表达式或计算属性的变化,并在回调函数中处理变化。
  • $set(target, key, value):在一个已有的响应式对象上添加一个属性,并确保这个新属性同样是响应式的,可以通过该方法解决对象添加新属性时无法响应式更新的问题。
  • $delete(target, key):删除一个对象的属性,可以通过该方法解决对象删除属性时无法响应式更新的问题。
  • $refs:一个对象,持有所有注册过 ref 的子组件。
  • $el:当前组件的根 DOM 元素。
  • $options:当前实例的初始化选项对象,包括组件的各种选项。

我们可以解析某个api源码

7.$nextTick源码

$nextTick是Vue.js框架中一个常用的异步更新方法,用于在下一次DOM更新循环结束后执行回调函数。

其源码如下:

Vue.prototype.$nextTick = function(fn) {
  return nextTick(fn, this)
}

// _nextTickId存储下一个tick的id号
let _nextTickId = 0
// _callbacks存储回调函数
let _callbacks = []
// _pending存储是否正在执行
let _pending = false

// nextTick函数
function nextTick(fn, ctx) {
  let id, callback
  callback = () => {
    // 如果传入了fn,则执行回调函数
    if (fn) {
      try {
        fn.call(ctx)
      } catch (e) {
        handleError(e, ctx, 'nextTick')
      }
    } else if (callback) {
      callback.id = null
      // 如果没有传入fn,但存在回调函数,则从_callbacks中移除该回调函数
      let index = _callbacks.indexOf(callback)
      if (index > -1) {
        _callbacks.splice(index, 1)
      }
    }
  }
  // 每次nextTick都会将该回调函数推入_callbacks中,等待执行
  _callbacks.push(callback)
  if (!_pending) {
    _pending = true
    // 使用微任务将回调函数异步执行
    if (typeof Promise !== 'undefined') {
      id = Promise.resolve().then(flushCallbacks)
    } else if (typeof MutationObserver !== 'undefined') {
      let observer = new MutationObserver(flushCallbacks)
      let textNode = document.createTextNode(String(_nextTickId))
      observer.observe(textNode, {
        characterData: true
      })
      id = () => {
        textNode.data = String(++_nextTickId)
      }
    } else if (typeof setImmediate !== 'undefined') {
      id = setImmediate(flushCallbacks)
    } else {
      id = setTimeout(flushCallbacks, 0)
    }
  }
  // 返回id,方便使用者手动取消nextTick
  if (!fn && typeof Promise !== 'undefined') {
    return id
  }
}

// flushCallbacks函数,用于执行_callbacks中的所有回调函数
function flushCallbacks() {
  _pending = false
  const copies = _callbacks.slice(0)
  _callbacks.length = 0
  for (let i = 0; i < copies.length; i++) {
    copies[i]()
  }
}

$nextTick方法首先将回调函数推入_callbacks数组中,并使用一个_pending变量记录是否有回调函数正在执行。

如果_pending为false,则说明当前没有回调函数正在执行,需要异步执行flushCallbacks函数,从而依次执行_callbacks数组中的所有回调函数。

在异步执行时,$nextTick方法会优先使用Promise的微任务方式执行回调函数,如果浏览器不支持Promise,则会尝试使用MutationObserver、setImmediate和setTimeout等方式执行。

当传入的回调函数为空时,$nextTick方法会返回一个id,方便使用者手动取消nextTick。

需要注意的是,$nextTick方法只会在组件实例的更新周期内生效,如果需要在Vue.js框架初始化后立即执行回调函数,可以使用Vue.nextTick()全局方法。

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。 

相关文章

  • vue3项目中使用tinymce的方法

    vue3项目中使用tinymce的方法

    这篇文章主要介绍了vue3使用tinymce的方法,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-04-04
  • vue3切换路由时页面空白问题解决办法

    vue3切换路由时页面空白问题解决办法

    在使用Vue3时,有时页面修改后会出现空白,这篇文章主要介绍了vue3切换路由时页面空白问题解决办法,文中介绍的步骤可以有效解决页面空白问题,需要的朋友可以参考下
    2024-09-09
  • VUE2.0中Jsonp的使用方法

    VUE2.0中Jsonp的使用方法

    使用JSONP主要是目的通过动态创建Script,动态拼接url,进而抓取数据,实现跨域。这篇文章主要介绍了VUE2.0中Jsonp的使用方法(前端),需要的朋友可以参考下
    2018-05-05
  • 关于vue文件中index.vue的使用方法

    关于vue文件中index.vue的使用方法

    这篇文章主要介绍了关于vue文件中index.vue的使用方法,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-10-10
  • 详解vue父子组件间传值(props)

    详解vue父子组件间传值(props)

    本篇文章主要介绍了详解vue父子组件间传值(props),小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-06-06
  • 详解vue移动端项目代码拆分记录

    详解vue移动端项目代码拆分记录

    这篇文章主要介绍了详解vue移动端项目代码拆分记录,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2019-03-03
  • vue3自定义指令自动获取节点的width和height代码示例

    vue3自定义指令自动获取节点的width和height代码示例

    这篇文章主要介绍了如何使用ResizeObserver监听组件的宽度和高度,并将其封装成一个指令以便全局或局部使用,ResizeObserver可以监听元素的多个尺寸属性,如top、bottom、left等,文中通过代码介绍的非常详细,需要的朋友可以参考下
    2024-11-11
  • LogicFlow内置菜单插件实例详解

    LogicFlow内置菜单插件实例详解

    这篇文章主要为大家介绍了LogicFlow内置菜单插件实例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-01-01
  • Vue使用Axios请求拦截器的案例详解

    Vue使用Axios请求拦截器的案例详解

    在Vue项目中,Axios是一个非常流行的HTTP客户端,用于发送请求和接收响应,Axios拦截器是Axios的一个强大功能,它允许你在请求发送之前和响应返回之后对请求和响应进行处理和拦截,本文将结合实际案例,详细介绍如何在Vue中使用Axios拦截器,需要的朋友可以参考下
    2024-12-12
  • vue实现拖拽窗口功能

    vue实现拖拽窗口功能

    这篇文章主要为大家详细介绍了vue实现拖拽窗口功能,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-04-04

最新评论