vue2.0与vue3.0

这里写自定义目录标题

  • Object.defineProperty
    • createApp
    • 自定义指令更新
    • to:body
    • data
    • 多根节点组件、函数式组件
    • 一些其他与开发者关系较为密切的更新
    • 最具有颠覆意义的响应-组合 API
    • 数据传递demo

Object.defineProperty

我们知道 Vue2 是响应式原理基于 Object.defineProperty 方法重定义对象的 getter 与 setter,vue3 则基于 Proxy 代理对象,拦截对象属性的访问与赋值过程。差异在于,前 者并不能对诸如数组长度变化、增删元素操作、对象新增属性进行感知,在 vue 层面不得不 重写一些数组方法(push、pop、unshift、shift 等),动态添加响应式属性,也要使用 $set 方法等。而 Proxy 则完美地从根上解决了这些问题,不过对于不支持 Proxy 对象的浏览器(如 IE),如果要使用 vue3 依然要进行降级兼容

createApp

import { createApp, defineAsyncComponent } from 'vue'
import App from './App.vue'
import MyApp from './MyApp.vue'

可以挂载两个实例,实现完全隔离

createApp. mount('#root')
createApp. mount('#app')

异步组件的使用,挂载到哪里就只能在注册那个地方实现

const app = createApp. mount('#root')

const AsyncComp = defineAsyncComponent(() => import('./components/AsyncComp.vue') ) app.component('async-component', AsyncComp);

1.异步组件在打包的时候分离出来了,可以缓存它,多个组件同时使用,可以复用。
2.提前用占位符代替,后面在慢慢加载

const myapp = createApp. mount('#app')

自定义指令更新

// vue2

bind - 指令绑定到元素后发生。只发生一次。
inserted - 元素插入父 DOM 后发生。
update - 当元素更新,但子元素尚未更新时,将调用此钩子。
componentUpdated - 一旦组件和子级被更新,就会调用这个钩子。
unbind - 一旦指令被移除,就会调用这个钩子。也只调用一次。.
// vue3
bind beforeMount
insertedmounted beforeUpdate :新的!这是在元素本身更新之前调用的,很像组件生命周期钩子。
update → 移除!有太多的相似之处要更新,所以这是多余的,请改用 updated。
componentUpdated updated beforeUnmount :新的!与组件生命周期钩子类似,它将在卸载元素之前调用。
unbind -> unmounted

to:body

比如一个弹框组件,要把它放到body 标签里去渲染,避免样式混淆<pop to:body></pop>;比如路由标题每个页面都有一个标题,是页面的属性,逻辑上是全局,业务上属于模块的

data

data 声明不再接收纯 JavaScript object,而必须使用 function 声明返回。

export default { data() { return { state: '', } } }

多根节点组件、函数式组件

多根节点允许 template 标签内直接出现多个子集标签,注意默认根节点需要明确指定。

<template>
<header></header>
<main v-bind $arrtr style={color:red}></main>
<footer><footer>
</template>

如果在main组件中,如果template只有一个子节点,会继承这个样式,如果有两个子节点,就不会继承样式了,需要在继承的那个节点使用$attrs

<template>
 <div id="">
 <div class="MultiNode" v-bind="$attrs">
      1
 </div>
 <div class="" v-bind="$attrs">
      2
 </div>
 </div>
</template>
// $attrs 默认本来绑定在唯一根节点上,多节点时需要明确指定挂在哪个节点下,用来指定继承父节点的属性

在 Vue 2 中,函数式组件有两个主要用例:

  1. 作为性能优化,因为它们的初始化速度比有状态组件快得多
  2. 返回多个根节点

Vue 3 中,函数式组件剩下的唯一用例就是简单组件。只能使用普通函数来声明。

// vue2 Functional.vue
<template>
<div>{{ msg }} </div>
</template>
<script>
export default { 
  functional: true, // 此处需要定义为ture 就可以使用函数式组件
    props: ['msg']
  }
</script>

// vue3 Functional.js 个人感觉好难用
import { h } from 'vue'
export default function Functional(props, context) {
return h('div',
context.attrs,  // 属性
props.msg  // children
)
}
Functional.props = ['msg']

一些其他与开发者关系较为密切的更新

在同一元素上使用的 v-if 和 v-for 优先级已更改。即 if 比 for 的优先级更高了;

vue3渲染函数不再提供 createElement 参数(通常简写为 h),而是从依赖中导入; 标签上的属性与绑定对象的属性冲突时,以排在后面的属性为准,不再给单独属性更高 的优先级。例如:

<your-comp name="Tom" v-bind="{ name: 'Jim' }" />
// vue2 your-comp 的 props:
name:'Tom'
// vue3 your-comp 的 props:
name:'Jim' 如果顺序是 <your-comp v-bind="{ name: 'Jim' }" name="Tom" />
则 vue2 和 vue3 的 props 均为
name:'Tom
如果顺序是 <your-comp v-bind="{ name: 'Jim' }" name="Tom" />
则 vue2 和 vue3 的 props 均为
name:'Tom'

最具有颠覆意义的响应-组合 API

这也是我们学习和转向 vue3 最有意义的一部分内容,可以这么说,如果没有掌握这一 部分内容,那么即使我们底层使用了 vue3,也不过是写 vue2。就像我们拥有了一台铲车, 却还在坚持靠人力把重物装卸到车叉上,只把铲车当运输工具一样。

setup 函数
组件创建前执行的初始化函数,默认参数包含 props 和 context。context 可以理解为 组件实例挂载之前的上下文(虽然这么理解,但不是实例本身,这点要清楚),所以实例上 的 attrs,slots,emit 可以在 context 上访问到。

reactive(深层) | readonly(只读) | shallowReactive(浅层) | shallowReadonly (只读浅层)
用于创建响应式的对象(只能是对象),isReactive 可以判断对象是否为响应式的。isProxy 区分是哪 种方法创建的代理对象,isReadonly 判断对象是否为 readonly(不可被修改) 创建。shallowXXX 根据名称 可知,只将对象自身的浅层属性进行转换,深层属性保持不变。

toRaw | markRaw
前者返回代理对象的源对象,后者将普通对象转换为不可代理的对象。

ref | toRef | unref | toRefs | isRef | shallowRef | triggerRef
常用于包装基本类型值为响应式对象,例如 const box = ref(0), box.value === 0 unref: isRef(data) ? data.value : data shallowRef:创建浅层的包装对象 triggerRef:人为触发订阅了 shallowRef 的副作用。

effect | watch | watchEffect
对数据源的更新订阅,一旦订阅的数据发生变化,将自动执行副作用函数。效果与 vue2 的 watch 配置类似。

computed
基于响应式数据生成衍生数据,且衍生数据会同步响应式数据的变化,效果与 vue2 的 computed 属性一样。

provide,inject
跨组件传递数据的方案。 基于 setup 方法使用的生命周期钩子同样有对应更新

基于 setup 方法使用的生命周期钩子同样有对应更新

beforeCreate -> setup()
created -> setup()
beforeMount -> onBeforeMount
mounted -> onMounted
beforeUpdate -> onBeforeUpdate
updated -> onUpdated
beforeUnmount -> onBeforeUnmount
unmounted -> onUnmounted
errorCaptured -> onErrorCaptured // 错误上报钩子,仅做了解
renderTracked -> onRenderTracked // { key, target, type } 仅做了解 renderTriggered -> onRenderTriggered // { key, target, type } 仅做了解

<template>
  <div @click="increment">
    compositionVue: {{data.count}}<br />
  </div>
  <span @click="pintCountRef">count: {{count}}</span>
  <p>f: {{f}}</p>
  <p>computedVal: {{computedVal}}</p>
</template>

<script>
import { reactive, toRaw, ref, effect, toRefs, watch, computed } from 'vue'
export default {
  setup(props, context) {
    const data = reactive({ count: 0, obj: {f: 2} })  // 定义了一个对象类型的 响应式对象
    
    const count = ref(0) // 定义了一个基本类型 响应式对象
    
    const pintCountRef = () => {
      
      console.log(++count.value)  // count 是一个对象, 使用count.value 来取值,标签里可以直接用,模板层面给解析出来了
    }
    
    const origin = toRaw(data) // 返回源对象,不用也不影响
    
    effect(() => {// pagination, search query  vue3 只关心变化了的值,变化之后,比如搜索功能,分页,查询参数,当变化的时候,不需要手动的调用请求
      console.log(data.count); // 副作用,如果使用了响应化数据,如果响应化数据有变化的时候就执行回调
    });
    
    
   /* watch([count, data.count], (value) => { //比vue2 有点变化
      // 第一个参数可以是函数,返回值变了就回调
      // 第一个参数可以是 ref / reactive,ref/reactive 值变了就回调
      // 第一个参数可以是 数组,数组每一项变了就回调
      alert(value)
    }); */
    
    watch(() => count.value > 5, (value) => { // 可以是条件,满足条件执行一次的效果
      // 第一个参数可以是函数,返回值变了就回调
      // 第一个参数可以是 ref / reactive,ref/reactive 值变了就回调
      // 第一个参数可以是 数组,数组每一项变了就回调
      alert(value)
    });
    
    function increment () {
      data.count++
      data.obj.f++ // 页面上的f 不会变,不是响应式变量,
    }
    
    const { f } = toRefs(data.obj);  // 基本值都是包装过的在解构
    // const f = ref(data.obj.f)
    
    const computedVal = computed(() => count.value + data.count); //计算衍生值 惰性的,只有变了才执行,不能对它进行重新赋值
    const computedVal2 = computed(() => count.value * data.count); // vue2里可以写多个,这里可以写一个,执行多次
    

    return { data, increment, count, pintCountRef, f, computedVal } // 在这里return 之后 template里才能获取
  }
  }
</script>

数据传递demo

// 父组件

export default {
  name: 'MyApp',
  // props: [''],
  data() {
    return {
      state: {
        value: 0
      }
    }
  },
  provide() { // 要传递给子组件的变量和方法
    return {
      state: readonly(this.state), // 使用readonly 子组件不能改
      onChange: () => {
        this.state.value = Math.random()
      }
    }
  },
  components: {  composition  }
}

// 子组件

import { h, reactive, inject, onMounted } from 'vue'


export default {
  setup(props, context) {
    const data = reactive({ count: 0 })
    
    const increment = () => {
      data.count++
    }
    
    const state = inject('state')  // 注入state 获取到父组件的state
    const onChange = inject('onChange') // 获取父组件的方法
    /* const onChange = () => {  // 直接变父组件的state,会导致父组件里的state变化,其他引用都会变化,会出问题
      state.value++
    } */
    
    onMounted(() => { // 不是生命周期的定义,是一个注册,可以注册多个;没有this
      console.log('task1')
    })
    
    onMounted(() => {
      console.log('task2')
    })
    
    return () => h('div', {
      onClick: onChange
    }, 'composition: ', data.count, 'state.value', state.value)
  }
}

终极简化:单文件组件 defineProps,defineEmits 直接在

// 在<script setup>内部的顶层变量,均能直接用于模板部分,
// 省略了 setup 函数及其返回值
<template>
<span @click="increment">{{count}}</span>
</template>
<script setup>
import { ref } from 'vue'
const count = ref(0)
const increment = () => {
count.value++
}
</script>

下面是自定义hooks demo

// customHooks

<template>
  customHook: {{loading ? '下载中' : '下载完成'}}<button @click="refresh">重试</button>
  <ul>
    <li v-for="{name, id} in info.value" :key="name">{{name}}</li>
  </ul>
</template>

<script>
  import useUserInfo from './hooks'
  import { ref, useSlots } from 'vue'
  export default {
    setup(props, { slots }) {
      const id = ref(0);
      const { info, loading } = useUserInfo(id);
      const refresh = () => {
        id.value++;
      }
      
      return { info, loading, refresh }
    }
  }
</script>

<style>
</style>

// hooks

import { ref, onMounted, watch, reactive } from 'vue'

const fetch = (id) => new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve([
      { name: 'user-' + Math.random(), id: 1 },
      { name: 'user-' + Math.random(), id: 2 },
      { name: 'user-' + Math.random(), id: 3 },
      { name: 'user-' + Math.random(), id: 4 },
      { name: 'user-' + Math.random(), id: 5 },
    ]);
  }, 200)
})

export default function useUserInfo(id) { // id 为响应式数据源
  const info = reactive({value: []})
  const loading = ref(false)

  const getUserInfo = () => {
    loading.value = true
    fetch(id.value).then(user => {
      info.value = user
      loading.value = false
    })
  }
  onMounted(getUserInfo)
  watch(() => id.value, getUserInfo);
  
  return { info, loading }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/598961.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

ComfyUI中的图像稀释处理

用下面的节点对图片进行稀释处理&#xff0c;如下 为0表示不变&#xff0c;我设置大一点&#xff0c;设置为0.5看看&#xff0c;如下 图像就暗淡了一些&#xff0c;但是还是有一些彩色的&#xff0c;相当于把它放在水里浸泡了一样&#xff0c;掉色了&#xff0c;这就是稀释&…

美国访问学者J1签证申请,这些关键事项一定要注意!

美国访问学者准备踏上学术探索之旅&#xff0c;申请J1签证是决定性的一步。以下是美国J1签证申请的一些关键注意事项&#xff0c;帮助你顺利通过签证流程&#xff1a; 1、签证类型&#xff1a;确认J-1签证是适合您访问学者身份的正确签证类型。 2、DS-2019表&#xff1a;在申…

2024------MySQL数据库基础知识点总结

-- 最好的选择不是最明智的&#xff0c;而是最勇敢的&#xff0c;最能体现我们真实意愿的选择。 MySQL数据库基础知识点总结 一、概念 数据库&#xff1a;DataBase&#xff0c;简称DB。按照一定格式存储数据的一些文件的组合顾名思义: 存储数据的仓库&#xff0c;实际上就是一…

工业光源环形系列一高均匀条形光源特点

产品特点 ◆可以根据检测需求随意调整照射角度&#xff1a; ◆可以根据检测需求选择光源颜色&#xff1a; ◆多个条形光源可以自由组合&#xff1a; ◆使用贴片灯珠&#xff0c;均匀性更好。

ICDE2024 |VDTuner:向量数据库自动调优技术

在CodeFuse接入实际业务的过程中&#xff0c;大模型的推理成本以及生成内容的准确性是产品规模落地的两个核心考量因素。为了降低推理成本&#xff0c;我们研发了CodeFuse-ModelCache语义缓存加速功能&#xff0c;通过引入Cache机制&#xff0c;缓存已经计算的结果&#xff0c;…

Spring Security基础教程:从入门到实战

作者介绍&#xff1a;✌️大厂全栈码农|毕设实战开发&#xff0c;专注于大学生项目实战开发、讲解和毕业答疑辅导。 推荐订阅精彩专栏 &#x1f447;&#x1f3fb; 避免错过下次更新 Springboot项目精选实战案例 更多项目&#xff1a;CSDN主页YAML墨韵 学如逆水行舟&#xff0c…

Windows系统安装MySQL数据库详细教程

【确认本地是否安装mysql】 &#xff08;1&#xff09;按【winr】快捷键打开运行&#xff1b; &#xff08;2&#xff09;输入services.msc&#xff0c;点击【确定】&#xff1b; &#xff08;3&#xff09;在打开的服务列表中查找mysql服务&#xff0c;如果没有mysql服务&am…

【WEB前端2024】开源智体世界:乔布斯3D纪念馆-第16课-跳转私信

【WEB前端2024】开源智体世界&#xff1a;乔布斯3D纪念馆-第16课-跳转私信 使用dtns.network德塔世界&#xff08;开源的智体世界引擎&#xff09;&#xff0c;策划和设计《乔布斯超大型的开源3D纪念馆》的系列教程。dtns.network是一款主要由JavaScript编写的智体世界引擎&am…

猫咪没精神不吃饭?这招主食冻干喂养教你让猫咪恢复食欲

猫突然不吃东西没精神是生病了吗&#xff1f;当猫咪不吃东西、精神不振时&#xff0c;可能的原因有健康问题、环境因素或食物原因。首先应进行身体检查&#xff0c;观察是否有其他并发症&#xff0c;如无则可排除健康问题。还要给猫咪提供一个舒适的环境&#xff0c;多给它们一…

Elsevier旗下双1区TOP刊,8.8分影响因子加上超低自引率,各指标领跑计算机类SCI

【SciencePub学术】 今天小编给大家带来了一本计算机类的高分优刊解读&#xff0c;隶属于Elsevier出版社&#xff0c;JCR1区&#xff0c;中科院1区TOP&#xff0c;影响因子高达8.7&#xff0c;领域相符的学者可考虑&#xff01; APPLIED SOFT COMPUTING 1 期刊概况 【期刊简…

从零开始搭建Springboot项目脚手架2:配置文件、返回值、日志等

1、多个环境与配置文件 2、统一返回值 返回值包括两种场景&#xff1a;正常controller的返回、异常发生之后返回 正常controller的返回&#xff1a;通过在controller的默认返回Response实现 异常发生之后返回&#xff1a;通过全局异常处理统一捕获返回 首先创建类StatusCode…

windows安装ElasticSearch以及踩坑

1.下载 elasticsearch地址&#xff1a;Past Releases of Elastic Stack Software | Elastichttps://www.elastic.co/cn/downloads/past-releases#elasticsearch IK分析器地址&#xff1a;infinilabs/analysis-ik: &#x1f68c; The IK Analysis plugin integrates Lucene IK…

C++:多态-重写和重载

重写&#xff08;Override&#xff09;和重载&#xff08;Overload&#xff09;是面向对象编程中常用的两个概念&#xff0c;它们虽然都涉及到方法的定义&#xff0c;但是在实现和使用上有着不同的特点。 重写&#xff08;Override&#xff09;&#xff1a; 重写是指在子类中重…

如何把视频转成文字稿?6个软件教你快速转换视频成文字

如何把视频转成文字稿&#xff1f;6个软件教你快速转换视频成文字 将视频转换为文字稿是一种有效的方式&#xff0c;可以帮助您提取视频中的信息并进行整理、编辑。以下是六个软件和工具&#xff0c;可以帮助您快速转换视频为文字稿&#xff1a; Google文档语音输入&#xf…

05-06 周一 Shell工程目录划分和开发最佳实践

05-06 周一 Shell工程目录划分和开发最佳实践 时间版本修改人描述2024年5月6日10:34:13V0.1宋全恒新建文档2024年5月6日11:07:12V1.0宋全恒完成 简介 之前楼主曾经完成过一个shell工程的开发&#xff0c;记得当时项目名称叫做campus-shell&#xff0c;主要是用来一键完成多个模…

高刚性滚柱直线导轨有哪些应用场景?

滚柱型滚动体取代了滚珠&#xff0c;由滚柱与导轨和滑块的线接触方式&#xff0c;滚柱导轨能在高负载的情况下仍然保持刚性值和高精度。为实现超高刚性和超重负荷能力而设计&#xff0c;整体滚柱导轨达到四方向等高刚性、高负载、高精度能力的特点&#xff0c;非常适合高速自动…

麦肯锡精英高效阅读法笔记

系列文章目录 如何有效阅读一本书笔记 读懂一本书笔记 麦肯锡精英高效阅读法笔记 文章目录 系列文章目录序章 无法读书的5个理由无法读书的理由① 忙于工作&#xff0c;没时间读书无法读书的理由② 不知应该读什么无法读书的理由③ 没读完的书不断增多无法读书的理由④ 工作繁…

[华为OD]C卷 精准核算检测 100

题目&#xff1a; 为了达到新冠疫情精准防控的需要&#xff0c;为了避免全员核酸检测Q带来的浪费&#xff0c;需要精准圈定可 能被感染的人群。现在根据传染病流调以及大数据分析&#xff0c;得到了每个人之间在时间、空间上是 否存在轨迹的交叉现在给定一组确诊人员编号&…

java面向对象实现文字格斗游戏

面向对象编程&#xff08;Object-Oriented Programming, OOP&#xff09;是一种程序设计思想&#xff0c;它利用“对象”来封装状态和行为&#xff0c;使得代码更易于维护和扩展。 下面我们使用java中的面向对象编程&#xff0c;来实现一个文字格斗的游戏联系&#xff01; 实…

多行字符串水平相加

题目来源与2023河南省ccpc statements_2.pdf (codeforces.com) ls [ ........ ........ .0000000 .0.....0 .0.....0 .0.....0 .0.....0 .0.....0 .0000000 ........ , ........ ........ .......1 .......1 .......1 .......1 .......1 .......1 .......1 ........, ......…
最新文章