vue3

参考来源,李南江:https://www.bilibili.com/video/BV14k4y117LL

一、创建vue3的三种方式:

  • vite
    vite是vue作者开发的一个项目打包工具,利用ES6的import会发送请求去加载文件的特性,拦截这些请求,做一些预编译,省去webpack冗长的打包时间。
// 1、安装Vite
npm install -g create-vite-app

// 2、创建vue3.0项目
create-vite-app 项目名称

// 3、切换至项目目录
cd 项目名称

// 4、安装依赖
npm install

// 5、运行项目
npm run dev
  • vue-cli
// 1、安装vue-cli
  npm install -g @vue/cli

// 2、创建vue项目
vue create 项目名称

// 3、切换至项目目录
cd 项目名称

// 4、添加vue3.0
vue add vue-next

// 5、运行项目
npm ru serve
  • webpack
// TODO

二、composition API

(1)、setup()函数:setup()函数是组合api的入口函数

setup()使用
  • 通常情况下是将业务处理的数据和事件抽离出去,如下所示:


    业务抽离
在第四步中,setup()return出去的方法和数据将会被vue注入data和methods中

1.1、composition API(vue3.0)可以和options API(vue2.x)混合使用。也就是data、computed、methods、setup可以混合使用

1.2、 composition API本质(组合API/注入API):
composition API return出去的数据将会注入到data中,return出去的方法将会注入到methods。

1.3 、setup()执行时机:
setup函数,是在vue生命周期beforecreate钩子之前完成的。

1.4、 setup注意点:

  • 在setup()函数中无法使用data、computed和methods(data、computed和methods是在生命周期created才初始化的)

  • setup()函数只能是同步的,不能是异步的。???????不理解!!!!

(2)、ref函数和reactive函数

2.1、reactive函数

  • reactive是vue3中实现响应式数据的方法:
    实现原理:vue2中响应式数据是通过defineProperty来实现的;vue3中响应式数据是通过ES6中的proxy来实现的,将传入数据包装成一个Proxy对象。

  • reactive的注意点:

 - reactive的参数必须是对象(json/数组)
 - 如果reactive传递了其他对象,
    +默认情况下修改对象,数据不会自动跟新(数据是单向的)
    +如果想更新,可以通过重新赋值的方式
 // 当传入对象为json或数组时
<template>
  <div>
    <div>{{obj}}</div>
    <input type="submit" @click="changeObj">
  </div>
</template>

<script>
import { reactive } from 'vue'  //1.引入reactive函数
export default {
  name: 'HelloWorld',
  setup () {
    // refactive本质上是把传入的数据包装成一个Proxy对象
    let obj = reactive({
      age: 12 // 2.通过reactive函数传入数据
    })

    function changeObj () {
      obj.age = 666 //3.改变对象数据
    }
    return { obj, changeObj }
  }
}
</script>

// 当传入其他对象时,需要重新赋值来实现响应式数据。
<template>
  <div>
    <div>{{obj.time}}</div>
    <input type="submit" @click="changeObj">
  </div>
</template>

<script>
import { reactive } from 'vue'
export default {
  name: 'HelloWorld',
  setup () {
    let obj = reactive({
      time: new Date()
    })

    function changeObj () {
      // 直接修改obj.time数据不会自动更新
      // obj.time.setDate(obj.time.getDate() + 1)
      // 重新赋值
      const newTime = new Date(obj.time.getTime())
      newTime.setDate(obj.time.getDate() + 1)
      obj.time = newTime
    }
    return { obj, changeObj }
  }
}
</script>

2.2、ref函数

  • ref 和reactive一样,也是用来实现响应式数据的方法
  • ref本质:ref底层还是reactive,vue会自动将ref传入的值转换为普通变量。例如:ref(3)=> reactive({ value: 3 })
  • 注意:template中使用ref,不用通过.value获取相应变量的值;但是在js中使用ref就需要通过.value来获取值。

2.3、ref函数和reactive函数的区别

1、如果在template'中使用ref类型的数据,vue会自动帮我们添加.value(obj.key)。
    如果在template中使用的是reactive类型的数据,vue不会自动添加obj.key,
    需要我们自己手动添加obj.key获取数据。

2、vue是如何判断当前数据是否为ref数据类型:
    vue通过私有属性__v_ref来判断的,若值为true则数据为ref类型;反之。

3、vue提供isRef和isReactive方法给我们判断当前数据类型为ref或reactive。
<template>
  <div>
    <div>{{ age }}</div>
    <input type="submit" @click="change">
  </div>
</template>

<script>
import { ref, reactive, isRef, isReactive } from 'vue'
export default {
  name: 'HelloWorld',
  setup () {
    let obj = reactive({age: 12})
    let age = ref(12)
    function change () {
      console.log(isRef(age)) //true
      console.log(isReactive(age))  //false
    }
    return { age, obj, change }
  }
}
</script>

console打印ref类型数据

(3)、toRef()方法

  • 3.1
<template>
  <div>
    <p>{{ students }}</p>
    <button @click="change">按钮</button>
  </div>
</template>

<script>
import { toRef } from 'vue'

export default {
  setup() {
    let obj = { name: 'nico' }
    let students = toRef(obj, 'name')

    function change() {
      students.value = 'allen'
      console.log(obj)
      console.log(students)
    }

    return {students, change}
  }
}
</script>

(4)、递归监听和非递归监听

1、递归监听:默认情况下,无论是通过ref还是reactive都是递归监听。

  • // 验证reactive是递归监听
// 验证reactive是递归监听
<template>
  <div>
    <div>{{ obj.a }}</div>
    <div>{{ obj.grandFather.b }}</div>
    <div>{{ obj.grandFather.father.c }}</div>
    <div>{{ obj.grandFather.father.son.d }}</div>
    <input type="submit" @click="change">
  </div>
</template>

<script>
import { ref, reactive } from 'vue'
export default {
  name: 'HelloWorld',
  setup () {
    let obj = reactive({
      a: 'a',
      grandFather: {
        b: 'b',
        father: {
          c: 'c',
          son: {
            d: 'd'
          }
        }
      }
    })
    function change () {
      obj.a = '1'
      obj.grandFather.b = '2'
      obj.grandFather.father.c = '3'
      obj.grandFather.father.son.d = '4'
    }
    return { obj, change }
  }
}
</script>
// 验证ref是递归监听
<template>
  <div>
    <div>{{ obj.a }}</div>
    <div>{{ obj.grandFather.b }}</div>
    <div>{{ obj.grandFather.father.c }}</div>
    <div>{{ obj.grandFather.father.son.d }}</div>
    <input type="submit" @click="change">
  </div>
</template>

<script>
import { ref, reactive } from 'vue'
export default {
  name: 'HelloWorld',
  setup () {
    let obj = ref({
      a: 'a',
      grandFather: {
        b: 'b',
        father: {
          c: 'c',
          son: {
            d: 'd'
          }
        }
      }
    })
    function change () {
// ref类型数据在js中需要通过.value获取变量的值
      obj.value.a = '1'
      obj.value.grandFather.b = '2'
      obj.value.grandFather.father.c = '3'
      obj.value.grandFather.father.son.d = '4'
    }
    return { obj, change }
  }
}
</script>

2、递归监听存在的问题:如果数据量比较大,递归监听是非常消耗性能的。

原理: vue3是通过把数据包装成proxy来实现响应式数据的。所以,递归监听是vue3将每一层变量递归取出包装成proxy。


console打印出每一层变量

3、非递归监听:只能监听变量的第一层,不能监听其他层。

  • 3.1、通过shallowReactive创建非递归监听。
创建reactive类型的非递归监听
reactive类型的非递归监听

如上图所示,只有第一层的数据被包装成proxy。vue只监听第一层数据的变化,若不修改第一层obj.a的数据,则视图不会发生更新。

  • 3.2、通过shallowRef创建Ref类型的非递归监听。
注意:如果是通过shallowRef创建的数据,那么vue3监听的是.value的变化,而不是第一层的变化。
若只修改某一层的数据,可使用tirggerRef()方法。
vue3只提供了triggerRef()方法,
没有提供triggerReactive()方法来出发某一层变量变化触发视图更新。
<template>
  <div>
    <div>{{ obj.a }}</div>
    <div>{{ obj.grandFather.b }}</div>
    <div>{{ obj.grandFather.father.c }}</div>
    <div>{{ obj.grandFather.father.son.d }}</div>
    <input type="submit" @click="change">
  </div>
</template>

<script>
// 1.引入triggerRef()方法
import { shallowRef, triggerRef } from 'vue'
export default {
  name: 'HelloWorld',
  setup () {
    let obj = shallowRef({
      a: 'a',
      grandFather: {
        b: 'b',
        father: {
          c: 'c',
          son: {
            d: 'd'
          }
        }
      }
    })
    function change () {
      obj.value.grandFather.father.son.d = '4'
//  2.triggerRef方法触发更新视图
      triggerRef(obj)
// Ref非递归监听中,vue3监听的是.value的变化,而不是第一层的变化。
      console.log(obj.value)
      console.log(obj.value.grandFather)
      console.log(obj.value.grandFather.father)
      console.log(obj.value.grandFather.father.son)
    }
    return { obj, change }
  }
}
</script>

  • 3.3、shallowRef和shallowReactive的本质。
  - shallowRef本质上是shallowReactive,调用shallowRef其实就是调用shallowReactive
     所以shallowRef创建的变量,vue3监听的是 .value的变化,本质上.value才是第一层
  • 3.4、应用场景:
    一般情况下使用ref和和reactive即可;只有监听数据量比较大的时候才使用shallowRef和shallowReactive。

4.toRaw()方法及其作用

  • toRaw用来获取ref和reactive的原始数据,也就是获取ref和reactive的引用。
// reactive数据类型
<template>
  <div>
    <p>{{ students }}</p>
    <button @click="change">按钮</button>
  </div>
</template>

<script>
import { reactive, toRaw } from 'vue'

export default {
  setup() {
    let obj = { name: 'nico', age: '21' }
    let students = reactive(obj)
    // console.log(obj === students) //false
    // 1.students和obj的关系是引用关系;students本质上是一个Proxy对象,这个Proxy对象引用了obj对象

    /*
    3.ref和reactive数据每次修改都会被监听,都会跟新视图层。
    如果我们一些逻辑操作是不需要被监听和更新视图层的,那么操作ref和reactive数据将会带来很大的性能消耗;
    在这种情况下,我们可以通过toRaw()方法拿到原始数据进行操作,这样就能提高性能。
    * */
    let obj2 = toRaw(obj)
    console.log(obj2 === obj) // true

    function change() {
      // 2.直接修改obj是无法触发视图层更新的
      // 只有通过修改Proxy包装之后的对象,才会触发视图层更新
      // obj.age = '18'
      // console.log(obj) // {name: "nico", age: "18"}
      // ---
      // students.age = '30'
      // console.log(students) // Proxy {name: "nico", age: "30"}
    }

    return {students, change}
  }
}
</script>

 // ref类型的数据
<template>
  <div>
    <p>{{ students }}</p>
  </div>
</template>

<script>
import { ref, toRaw } from 'vue'

export default {
  setup() {
    let obj = { name: 'nico', age: '21' }
    let students = ref(obj)
    //ref类型数据要通过.value来获取
    let obj2 = toRaw(students.value)

    console.log(obj)
    console.log(students)
    console.log(obj2)
    
    return {students}
  }
}
</script>

5 .markRaw()方法可以将数据设置为非响应式数据

<template>
  <div>
    <p>{{ students }}</p>
    <button @click="change">按钮</button>
  </div>
</template>

<script>
import { reactive, markRaw } from 'vue'

export default {
  setup() {
    let obj = { name: 'nico', age: '21' }
    obj = markRaw(obj) //obj将永远不被追踪
    let students = reactive(obj)

    function change() {
      students.name = 'allen'
      console.log(students)
    }

    return {students, change}
  }
}
</script>
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 222,104评论 6 515
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 94,816评论 3 399
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 168,697评论 0 360
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,836评论 1 298
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,851评论 6 397
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 52,441评论 1 310
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,992评论 3 421
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,899评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,457评论 1 318
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,529评论 3 341
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,664评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 36,346评论 5 350
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 42,025评论 3 334
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,511评论 0 24
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,611评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 49,081评论 3 377
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,675评论 2 359

推荐阅读更多精彩内容