jquery on 动态绑定事件-Vue.js 四个重要知识点总结

refto概述ReftoRefs高级深入理解

1. 为什么需要ref?

1.返回值类型会失去响应

2.Setup、计算和合成函数都可以返回值类型。

3.如果Vue没有定义ref,用户就会自定义ref,这样会造成混乱。

2. 为什么需要.value?

1.ref是一个对象(不失去响应能力),value存储值

2.通过.value属性的get和set实现响应能力

3、在templates和reactive中使用时,.value不是必需的,但在其他情况下是必需的。

3. 为什么需要toReftoRefs

1.初衷:在不损失响应性的情况下分解和扩散对象数据

2.前提:目标是响应对象,而不是普通对象

3. 注意:不要创建响应性,而是继续响应性。

更多精彩内容请在陌陌上搜索“前端爱好者”查看。

vue3设置

脚本安装程序有什么作用?

scrtptsetup是vue3的语句糖,简化了组合API的编写,并且有更好的运行性能。

使用scriptsetup语句糖的特点:

如何在设置中获取组件实例? vue3getCurrentInstance

在Vue2中,可以通过this获取当前组件实例;

在Vue3中,setup中无法通过this获取组件实例,console.log(this)复制的值是未定义的。

Vue3中,可以使用getCurrentInstance()获取当前组件实例 vue3官方文档解释

let { proxy } = getCurrentInstance();

复制setup中以下三个值,结果如下:

console.log(getCurrentInstance,typeof(getCurrentInstance));
console.log(getCurrentInstance(),typeof(getCurrentInstance()));
console.log(proxy,typeof(proxy));

结果

你可以看到:

getCurrentInstance 只能在设置或生命周期挂钩中使用。

在 onMunted 生命周期中复制 getCurrentInstance

定义一个测试方法,点击风暴触发

onMounted(() => {
  console.log(getCurrentInstance(), typeof getCurrentInstance());
});
function test() {
  console.log(getCurrentInstance(), typeof getCurrentInstance());
}

可见函数中获取实例是比较困难的。

let { ctx } = getCurrentInstance();
console.log(ctx, typeof ctx);
let { proxy } = getCurrentInstance();
console.log(proxy, typeof proxy);

ctx和proxy都是getCurrentInstance()对象中的属性,它们以重构参数的形式接收。 正如您所看到的,两者之间存在差异。

ctx是普通对象,proxy是Proxy对象。

补充:Vue3中关于getCurrentInstance的坑

开发时jquery on 动态绑定事件,只适合调试! 请勿在有线环境下使用,否则会出现问题!

解决方案:

计划1.

获取全局挂载的方式

const instance = getCurrentInstance()
console.log(instance.appContext.config.globalProperties)

场景2。

如果你上网使用代理就不会有问题

const { proxy } = getCurrentInstance()  

为什么Vue3比Vue2更快?

1. Proxy实现响应式

2. 补丁标志

1、编译模板时,标记动态节点

2.标签,分为不同类型,如TEXT、PROPS

3. diffing时区分静态节点和不同类型的动态节点

3. 提升机静态

1.改进静态节点的定义到父作用域,缓存起来jquery on 动态绑定事件,用空间换时间

2、多个相邻的静态节点会被合并编译进行优化

4.cacheHandler缓存争议

5、SSR优化静态节点直接输出为dom,绕过vdom

6.编译tree-shaking时,按需导入API

如何理解Vue的双向数据流?

所有 props 都会促进其父 props 和子 props 之间的双向下游绑定:

父组件的更新会流向子组件,反之则不然。 这可以避免子组件意外更改父组件的状态,从而导致应用程序的数据流难以理解。

另外,每次父组件更新时,子组件中的所有 props 都会刷新为最新值。 这意味着您不应该更改子组件内的 props。

如果您这样做,Vue 将在浏览器的控制台中发出警告。 当子组件想要改变的时候,只能通过$emit发送自定义的storm,父组件收到后才会改变。

尝试改变 prop 的常见情况有两种:

该prop用于传递初始值; 该子组件已连接并希望将其用作本地道具数据。

在这些情况下,最好定义一个本地数据属性并使用此属性作为其初始值:

props: ['initialCounter'],
data: function () {
  return {
    counter: this.initialCounter
  }
}

该 prop 作为原始值传入,需要进行转换。

在这些情况下,最好使用此 prop 的值来定义估计的属性

props: ['size'],
computed: {
  normalizedSize: function () {
    return this.size.trim().toLowerCase()
  }
}

Vue中风波绑定的原理$emit

vm.$emit('事件名称', 可选参数)

在当前实例上触发风暴,将要传输的数据传递给窃听者;

$上

vm.$on('事件名称', callback) callback回调emit要传送的数据

窃听当前实例上的自定义风暴;

折扣$

vm.$off( [event, callback] )

删除了自定义风暴错误。

vue2 用例

//父组件

  


  data () {
   return {
    selectType: 0,
  },
  methods: {
   onSelectType (type) {
    this.selectType = type
   }
  }

父组件使用@select-type="onSelectType"@,即v-on的缩写,监听子组件vm.$emit触发的风暴,通过onSelectType接受子组件传过来的数据(),并通知父组件数据变化。

// 子组件

 

  
  
  
 



  data () {
   return {
    selectType: 0,
  },
  methods: {
    select (type, event) {
      this.selectType = type
      this.$emit('select-type', type)
   }
  }

子组件通过$emit触发storm并传递参数。

vue3使用示例--Vue3.x推荐使用外部库mitt来替换$on$emit$off

mitt 源代码是使用 typescript 编译的。 源代码加上注释一共不到90行,比较容易阅读。

Typescript不是本文的重点,所以mitt源码以js形式展示如下。

/**
 * 向外暴露的默认函数
 * @param 入参为 EventHandlerMap 对象 (ts真香,我们能清楚的知道参数的类型是什么,返回值是什么)
 * @returns 返回一个对象,对象包含属性 all,方法 on,off,emit
 */
export default function mitt (all) {
  /*
    此处实参可传一个EventHandlerMap对象,实现多个 mitt 的合并。例如:
    const m1 = mitt();
    m1.on('hi', () => { console.log('Hi, I am belongs to m1.'); });

    const m2 = mitt(m1.all);
    m2.emit('hi') // Hi, I am belongs to m1.
    m2.on('hello', () => { console.log('Hello, I am belongs to m2.'); });

    m1.emit('hello'); // Hello, I am belongs to m2.

    m1.all === m2.all // true
  */
  all = all || new Map();

  return {
    // 事件键值对映射对象
    all,

    /**
     * 注册一个命名的事件处理
     * @param type 事件名,官方表示事件名如是 *,用来标记为通用事件,调用任何事件,都会触发命名为 * 的事件
     * @param handler 事件处理函数
     */
    on (type, handler) {
      // 根据type去查找事件
      const handlers = all.get(type);
      // 如果找到有相同的事件,则继续添加,Array.prototype.push 返回值为添加后的新长度,
      const added = handlers && handlers.push(handler);
      // 如果已添加了type事件,则不再执行set操作
      if (!added) {
        all.set(type, [handler]); // 注意此处值是数组类型,可以添加多个相同的事件
      }
    },

    /**
     * 移除指定的事件处理
     * @param type 事件名,和第二个参数一起用来移除指定的事件,
     * @param handler 事件处理函数
     */
    off (type, handler) {
      // 根据type去查找事件
      const handlers = all.get(type);
      // 如果找到则进行删除操作
      if (handlers) {
        // 这里用了个骚操作,其实就是找到了,则删除(多个相同的只会删除找到的第一个),没找到则不会对原数组有任何影响
        handlers.splice(handlers.indexOf(handler) >>> 0, 1);
      }
    },

    /**
     * 触发所有 type 事件,如果有type为 * 的事件,则最后会执行。
     * @param type 事件名
     * @param evt 传递给处理函数的参数
     */
    emit (type, evt) {
      // 找到type的事件循环执行
      (all.get(type) || []).slice().map((handler) => { handler(evt); });
      // 然后找到所有为*的事件,循环执行
      (all.get('*') || []).slice().map((handler) => { handler(type, evt); });
    }
  };
}

vue3mitt 使用 mitt 优势 API

// 创建mitt实例
mitt()

// 事件名称到注册处理程序函数的映射。
all

//触发事件,两个参数:name:触发的方法名,data:需要传递的参数
emit(name,data) 

// 绑定事件,两个参数:name:绑定的方法名,callback:触发后执行的回调函数
on(name,callback) 

// 解绑事件,一个参数:name:需要解绑的方法名
off(name)  

安装手套:

npm install mitt -save

创建一个新的 EventBus.js 文件:

// 事件总线第三方库:
import mitt from 'mitt';
const bus = mitt();
export default bus;

案例使用

引起骚乱的页面:send.vue


    

        

send页面视图


        
    

    

 

import bus from "../utils/EventBus" 
const sendData = () => {
  bus.emit("data",18)
}
 

接收storm的页面:response.vue


    

        

response页面视图


    


 

import bus from "../utils/EventBus"
import { ref ,onMounted} from "vue";
onMounted(()=>{
    bus.on("data",(info)=>{
      // info 就是emit传过来的数据
      console.log("dd页面接收到的值:",info)
    })
}) 

消除窃听

Bus.off('Event');

参考地址: