Vue3

一 vue3 介绍

1 Vue3的变化

1.1 性能的提升

  • 打包大小减少41%
  • 初次渲染快55%, 更新渲染快133%
  • 内存减少54%

1.2 源码的升级

  • 使用Proxy代替defineProperty实现响应式
  • 重写虚拟DOM的实现和Tree-Shaking

1.3 拥抱TypeScript

  • Vue3可以更好的支持TypeScript

1.4 新的特性

  1. Composition API(组合API)
  • setup配置
  • ref与reactive
  • watch与watchEffect
  • provide与inject
  1. 新的内置组件
  • Fragment
  • Teleport
  • Suspense
  1. 其他改变
  • 新的生命周期钩子
  • data 选项应始终被声明为一个函数

2 组合式api和配置项api

  • 组合式api
    都写到一个函数中,定义变量和定义方法,定义计算属性都是放在一起,不是拆到不同地方了

  • 配置项api:之前vue2中的写法

	new Vue({
        data:{
            name:'lqz'
        },
        methods:{
            # 使用变量
        }
    })

3 vue3 之vue实例

# vue3的app实例
	也是个对象,但是以后我们使用东西,不是从this中拿了,this当没了

# vue2的app实例
	就是咱们再组件中用的this
    this.$store
    this.$refs....
    
   
# 以后真正vue3的语法,写法可能变了

4 创建vue3 项目

4.1 使用 vue-cli 创建

官方文档:https://cli.vuejs.org/zh/guide/creating-a-project.html#vue-create

# vue3 完全兼容vue2 


-vue create vue_cli_test

-路由选择,选择vue3即可
-跟之前创建vue2是一样的

4.2 使用 vite 创建

-vite:vue_vute_test
    npm init vue@latest
    按下图选择

  • 工具链,构建工具
    • 之前咱们再html中写,可能js可以引入
    • 可能写了一些 es高版本的语法----> 转成低版本
    • 可能写 xx.vue,浏览器识别不了,浏览器只能识别:html,css,js
    • 咱们需要 有个东西可以一次性把 es高版本转成低版本,把xx.vue 转成xx.js的方式
    • 工具链:
      • webpack
      • vite

5 setup

# setup是个函数,以后vue的代码,都写在这里面
	1 里面可以定义变量
    2 可以定义函数,可以定义匿名函数
    3 如果想在templage中使用,必须return
    4 如果要对变量加入响应式,需要使用ref包裹变量
    5 data,methods都可以用,但是是setup函数先执行,才走其它
    6 template中使用函数,变量,都优先用setup中的
    7 setup最先执行,是再生命周期的beforeCreate前执行的,内部没有this,也不能用this了

6 响应式

6.1 ref函数

# 包裹变量,实现响应式
let name = ref('lqz')
<template>
  <div class="home">
    名字是:{{ name }},年龄是:{{ age }},爱好:{{ hobby }}
    <br>
    <button @click="handleAdd">点我涨年龄</button>
    <br>
    <button @click="handleChange">点击变名字</button>
  </div>
</template>

<script>


// 导入ref函数
import {ref} from 'vue'

export default {
  name: 'HomeView',
  // 这样写支持
  data() {
    return {
      // hobby: '篮球'
      hobby: this.name + '爱打篮球'
    }
  },
  methods: {
    handleAdd() {
      console.log('methods中的handleAdd')
    }
  },

  // 以后我们写成这样,
  setup() {
    // 以后所有vue3的代码,都写在这里面
    //原来写在data中定义变量
    // 如果想在view中使用定义的变量,必须retur出去
    // var:老语法     let:以后定义变量用这个    const :定义常量

    // 1 定义变量,并再页面中渲染
    // const name = 'lqz'
    // const age = 19
    // return {name,age}
    // // return {name:name,age:age}


    // 2 定义变量和函数,再页面中使用---->失去了响应式
    // let name = 'lqz'
    // let age = 19
    // const handleAdd = () => {
    //   // alert('我被点了')
    //   // alert(add(4,5))
    //   age = age + 1
    //   console.log(age)
    //
    // }
    //
    // function add(a, b) {
    //   return a + b
    // }
    //
    //
    // return {name, age, handleAdd}


    // 3 加入响应式
    //   let name = ref('lqz')
    //   let age = ref(19)  // 他就变成了响应式
    //   const handleAdd = () => {
    //     console.log(age)
    //     console.log(typeof age)
    //     // age = age + 1
    //     // 以后需要用那个之,需要 对象.value才能取出来
    //     age.value = age.value + 1
    //     console.log(age)
    //
    //   }
    //
    //   const handleChange = () => {
    //     // name.value = '彭于晏'
    //     name.value = name.value+'nb'
    //     console.log(name)
    //   }
    //
    //   return {name, age, handleAdd, handleChange}

    // 4 研究一下,原来的data,methods还能不能用
    let name = 'lqz'
    let age = 19
    // const handleAdd = () => {
    //   console.log('setup中的handleAdd')
    // }
    console.log('---',this)
    return {name, age,}

  }
}
</script>

6.2 reactive函数

### 使用方式
<template>
  <div class="home">
    <h1>首页</h1>
    <!--    名字是:{{ name.value }}-->

    名字是:{{ data.name }}---->年龄:{{ data.age }}
    <button @click="handelAdd">点我加年龄</button>
  </div>
</template>

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

export default {
  name: 'HomeView',
  setup() {
    // 1 要让变量有响应式,要用ref包裹一下,包裹的都是字符串,数字,布尔
    // js中再使用这个变量取值赋值是要  变量名.vaule 使用
    // template中使用变量不要用.value
    // let name = ref('lqz')
    // name.value = '彭于晏'
    // return {name}


    // 2 如果想让对象有响应式,reactive
    let data = reactive({'name': 'lqz', 'age': 19, 'hobby': '篮球'})
    const handelAdd = () => {
      data.age += 1  // 使用reactive包裹的对象,直接当对象用即可
      console.log(data)
    }
    return {data, handelAdd}
  }
}
</script>

7 reactive与ref对比

  • 从定义数据角度对比:

    • ref用来定义:基本类型数据
    • reactive用来定义:对象(或数组)类型数据
  • 从原理角度对比:

    • ref通过Object.defineProperty()的get与set来实现响应式(数据劫持)。
    • reactive通过使用Proxy来实现响应式(数据劫持), 并通过Reflect操作源对象内部的数据。
  • 从使用角度对比:

    • ref定义的数据:操作数据需要.value,读取数据时模板中直接读取不需要.value。
    • reactive定义的数据:操作数据与读取数据:均不需要.value。

8 计算,监听属性

8.1 监听属性

### 监听属性  就是使用watch,三种方式
    # 导入
    import {watch} from "vue";

	#  1 方式一
    watch(name, (newValue, oldValue) =>{
      console.log(newValue)
      console.log(oldValue)
      console.log('name 真的变了...')
    })

    # 2 监听属性之监听对象中的某个属性
    let person = reactive({name: 'lqz', age: 19})
    watch(() => person.name, () => {
      console.log('person中的name变了')
    })
    const handleChanel = () => {
      person.name = '刘亦菲'
    }
    # 3 同时监听多个变量
    # 3.1 监听两个变量
    const sum = ref(100)
    const msg = ref('很好')
    watch([sum, msg], (newValue, oldValue) => {
    console.log('sum或msg变化了', newValue, oldValue)
    })
    
    # 3.2 监听变量和对象
    watch([age, () => info.username], (newValue, oldValue) => {
      console.log('年龄或对象中的用户名变化了', newValue, oldValue)
    })

8.2 计算属性

  • 计算属性 使用computed ,只有取值触发或取值赋值触发函数
<template>
  <div class="home">
    <h1>首页</h1>
    <input type="text" v-model="name"> ---> {{ newName }}
    <br>
    <input type="text" v-model="newName2">
  </div>
</template>

<script>
import {ref, reactive} from "vue";
import {computed} from "vue";

export default {
  name: 'HomeView',
  setup() {
    let name = ref('')
    // 1 计算属性取值
    let newName = computed(() => {
      return name.value + 'nb'
    })

    // 2 了解:计算属性可以取值用,还可以改值
    let newName2 = computed({
      get() {
        // 使用计算属性,会触发这里
        return name.value + '=nb'
      },
      set(value) {
        // 只要计算属性发生变化,就会执行这里
        console.log('计算属性变了,变成', value)

        // 只要newName变了,name理应该也变,需要我们写代码变
        let res = value.split('=')
        name.value = res[0]
      }
    })
    return {name, newName, newName2}
  },
}
</script>

9 生命周期

# 8 个生命周期钩子

# vue3不建议使用 配置项api,把所有代码都写在setup函数中
	-以后没有:destory这俩了,换成了unmounted
    -可以写配置项api(练习一下)但是不建议写了
    	beforeCreate
        created
        beforeMoun
        mounted
        beforeUpdate
        updated 
        beforeUnmount 
        unmounted 
    -写组合式api
    	beforeCreate===>setup()
        created=======>setup()
        beforeMount ===>onBeforeMount
        mounted=======>onMounted
        beforeUpdate===>onBeforeUpdate
        updated =======>onUpdated
        beforeUnmount ==>onBeforeUnmount
        unmounted =====>onUnmounted

组件的生命周期钩子vue2使用

export default {
  // 生命周期
  // beforeCreate
  // created
  // beforeMount
  // mounted
  // beforeUpdate
  // updated
  // beforeUnmount
  // unmounted
  created() {
    console.log('创建了')
  },
  beforeUnmount() {
    console.log('beforeUnmount')
  },
  unmounted() {
    console.log('unmounted')
  },
}

vue3使用生命周期钩子

HomeView.vue

<template>
  <div class="home">
    <h1>首页</h1>
    <button @click="handleShow">点我显示</button>
    <HelloWorld v-if="show"></HelloWorld>
  </div>
</template>

<script>
import {ref} from "vue";
import HelloWorld from "@/components/HelloWorld";

export default {
  name: 'HomeView',
  setup() {
    let show = ref(true)
    const handleShow = () => {
      show.value = !show.value
    }
    return {show, handleShow}
  },
  components: {
    HelloWorld
  }
}
</script>

HelloWorld.vue

<template>
  <div class="hello">
    <h1>HelloWorld页面</h1>
  </div>
</template>

<script>
import {ref} from "vue";
import {onBeforeMount, onMounted, onBeforeUpdate, onUpdated, onBeforeUnmount, onUnmounted, reactive} from 'vue'

export default {
  name: 'HelloWorld',
  setup() {
    // 生命周期钩子
    // beforeCreate===>setup()
    // created=======>setup()
    // beforeMount ===>onBeforeMount
    // mounted=======>onMounted
    // beforeUpdate===>onBeforeUpdate
    // updated =======>onUpdated
    // beforeUnmount ==>onBeforeUnmount
    // unmounted =====>onUnmounted

    console.log('vue组件创建了(包含beforeCreate,created)')
    // 1 如果想组件创建完成,就发送ajax请求,直接写在setup里面即可

    // let name = ref('')
    // axios.get('地址').then(res => {
    //   name.value = res.data.name
    // })

    // 2 原来写在created中的,直接写在下面即可,直接在这开启定时器
    var t = setInterval(() => {
      console.log('hello world')
    }, 1000)


    onBeforeUnmount(() => {
      console.log('onBeforeUnmount')
      // 消除定时器
      clearInterval(t)
      t = null
    })
    onUnmounted(() => {
      console.log('onUnmounted')
    })
  },
}
</script>

10 toRef

# ...{对象} ---> 相当于解压
# 再setup函数中return时,使用return {...toRefs(data)},以后再templte中直接使用内层的变量即可


  setup() {
    let a = {hobby: '篮球', gender: '男'}
    console.log(a)
    let b = {...a, name: 'lqz'}
    console.log(b)
  },

基本使用

<template>
  <div class="home">
    <h1>首页</h1>
    {{ name }} --- {{ age }}
    <br>
    <button @click="handleClick">点我看美女</button>
    <br>
    <button @click="handleAdd">点我改年龄</button>
  </div>
</template>

<script>
import {ref, reactive, toRefs} from "vue";

export default {
  name: 'HomeView',
  setup() {
    let data = reactive({name: 'lqz', age: 19})
    const handleClick = () => {
      alert('美女')
    }
    const handleAdd = () => {
      data.age += 1
    }
    // ...toRefs(data)  等同于  {name:data.name,age:data.age}
    // return {name: data.name, age: data.age, handleClick}
    return {...toRefs(data), handleClick, handleAdd}
  },
}
</script>

二 Vite创建项目

官方文档:https://v3.cn.vuejs.org/guide/installation.html#vite

vite官网:https://vitejs.cn

介绍:https://cn.vitejs.dev/guide/why.html#the-problems

  • 什么是vite?—— 新一代前端构建工具。
  • 优势如下:
    • 开发环境中,无需打包操作,可快速的冷启动。
    • 轻量快速的热重载(HMR)。
    • 真正的按需编译,不再等待整个应用编译完成。
      传统构建 与 vite构建对比图
# 确保你安装了最新版本的 Node.js,然后在命令行中运行以下命令
cnpm init vue@latest

# 安装依赖
cnpm install
# 运行
cnpm run dev

2.1 vue3 setup写法

<script setup>
// <script setup> 表示,这个script里的所有东西是setup函数,原来写在setup中的,现在顶格写即可
import {ref, reactive} from "vue";

let name = ref('lqz')
const handelClick = () => {
  name.value = '彭于晏'
}
// 不需要return,直接使用即可

let info = reactive({hobby: ['篮球'], addr: '上海'})
const handleInfo = () => {
  info.hobby.push('足球')
}

// watch,computed
// 生命周期钩子
// 组件导入,自动注册

import HelloWorld from "@/components/HelloWorld.vue";
</script>

<template>

  <h1>我是首页</h1>
  {{ name }}
  <br>
  <button @click="handelClick">点我变名字</button>
  <h1>对象</h1>
  {{ info.hobby }} --- {{ info.addr }}
  <br>
  <button @click="handleInfo">点我加爱好</button>

  <h1>使用组件</h1>
  <HelloWorld msg="HelloWorld"></HelloWorld>

</template>

posted @ 2023-06-13 19:12  星空看海  阅读(41)  评论(0编辑  收藏  举报