Vue3

一、创建vue3项目

1、官网

https://cn.vitejs.dev/guide/

2、创建项目

# 使用npm
npm create vite@latest

3、vite为什么这么快

- 冷启动  - 热加载  - 按需编译

二、setup函数

1、setup特性

  • setup为Vue3.0中一个新的配置项,值为一个函数
  • setup是所有Composition API(组合API)编写的位置
  • 组件中所用到的:数据、方法等等,均要配置在setup中
  • setup函数的返回值:返回一个对象,对象中的属性、方法, 在模板中均可以直接使用 

注意:

  • 尽量不要与Vue2.x配置混用
  • Vue2.x配置(data、methos、computed...)中可以访问到setup中的属性、方法。
  • 但在setup中不能访问到Vue2.x配置(data、methos、computed...)。
  • 如果有重名, setup优先。

2、示例:

<template>
  {{name}}--{{age}}--{{xx}}
</template>

<script>

export default {
  name: 'App',
  data(){
    return {
      xx:this.name
    }
  },
  setup(){
    let name='lqz'
    let age =19
    return {
      name,age
    }
  },
}
</script>

3、setup执行的时机

在Vue 3中,setup函数是用来配置组件的入口点。它是在组件实例创建之前执行的,而不是在beforeCreate钩子之前执行。这是因为setup函数的目的是为了设置组件的响应式数据、

计算属性、方法等,它会返回一个对象,包含这些配置项,然后这些配置项将会被合并到组件实例中。

在beforeCreate之前执行一次,this是undefined。

# setup的参数
props:值为对象,包含:组件外部传递过来,且组件内部声明接收了的属性。
context:上下文对象
attrs: 值为对象,包含:组件外部传递过来,但没有在props配置中声明的属性, 相当于 this.$attrs。
slots: 收到的插槽内容, 相当于 this.$slots。
emit: 分发自定义事件的函数, 相当于 this.$emit。

# 总结:
	setup执行是在beforeCreate,没有this对象,以后不要用this了
    
	如果写setup函数,想接收父组件自定义属性传入的值,需要
        export default {
          setup(props) {
            console.log(props.msg)
          },
          props: ['msg']
        }
        
    如果是vue3的最新写法,想接收父组件自定义属性传入的值,需要
    <script setup>
    defineProps(['msg'])
    </script>  

4、vue3兼容vue2,但是最好不要混用

<template>
  <div class="home">
    <p>我的名字是:{{ name }}</p>
    <p>我的年龄是:{{ age }}</p>
    <button @click="handleClick">点我看信息</button>
  </div>
</template>

<script>

export default {
  setup() {
    // 1 定义数据
    const name = 'lqz'
    let age = 19
    // 2 定义方法
    const showInfo = () => {
      alert(`姓名是:${name},年龄是:${age}`)
    }

    return {name, age, showInfo}

  },
  methods: {
    handleClick() {
      alert(`姓名是:${this.name},年龄是:${this.age}`)
    }
  }
}
</script>

三、ref函数

1、ref函数绑定响应式

导入ref:import {ref} from 'vue'

<template>
  <div class="home">
    <p>我的名字是:{{ name }}</p>
    <p>我的年龄是:{{ age }}</p>
    <button @click="handleAdd">点我年龄+1</button>
    <button @click="handleChangeName">点我秒变彭于晏</button>
  </div>
</template>

<script>

// 变量要具备响应式---》页面内容变化,变量和变,变量变化,页面也变
// 普通变量,通过ref绑定响应式
// 引用类型变量:通过reactive 绑定响应式
import {ref} from 'vue'

export default {

  setup() {
    // 1 定义数据
    let name = ref('lqz')
    let age = ref(19)
    // 2 定义方法
    const handleAdd = () => {
      age.value += 1
      console.log(typeof age)
    }

    const handleChangeName = () => {
      name.value = '彭于晏'
    }

    return {name, age, handleAdd,handleChangeName}

  },
}
</script>

2、vue3中使用const定义方法和使用let定义方法的场景

在Vue 3中,通常会使用constfunction关键字来定义组件的方法。使用const关键字定义方法是合法的,

当你使用const定义方法时,它会被视为一个常量,意味着它不会在每次重新渲染组件时被重新创建。这种优化可以提高性能,因为不需要在每次渲染时重新创建方法。

然而,如果你使用const定义一个方法,并且该方法内部依赖于组件的响应式数据或属性,可能会遇到问题。因为常量方法内部无法访问响应式数据。在这种情况下,你应该使用function关键字定义方法,或者将方法定义为组件的实例方法,以确保它可以访问到组件的响应式数据。

使用let定义方法通常不是一个好的做法,因为它会导致方法在每次重新渲染时被重新创建,这可能会影响性能。然而,在某些特殊情况下,你可能希望在每次渲染时都创建一个新的方法实例,这时使用let定义方法就是合适的。

四、reactive函数

1、父组件

<template>
  <div class="home">
    <p>我的名字是:{{ data.name }}</p>
    <p>我的年龄是:{{ data.age }}</p>
    <p>我的爱好是:{{ hobby }}</p>
    <button @click="addAge">点我年龄+1</button>
    <br>
    {{ obj.hobby }}
    <br>
    <button @click="changeHobby">点我把保龄球换成足球</button>
    <hr>
    <h2>这里是父传子的消息</h2>
    <HelloWorld msg="我是你baba发过来的"></HelloWorld>
  </div>
</template>

<script>

import {reactive, ref} from 'vue'
import HelloWorld from "@/components/HelloWorld.vue";

export default {
  setup() {
    let hobby = ref('篮球')
    let obj = ref({
      age: 99,
      hobby: '保龄球'
    })

    const changeHobby = () => {
      console.log(obj)
      obj.value.hobby = '足球'
    }

    let data = reactive({
      name: '彭于晏',
      age: 19
    })
    
    const addAge = () => {
      //data.age++
      console.log(typeof data)
      console.log(data) // 是一个代理对象,无法拿出原来对象,但是操作起来跟操作源对象一样
      data.age++
    }
    return {hobby, data, addAge, obj, changeHobby}

  },
  components: {
    HelloWorld
  }

}

</script>

补充:

/*ref
作用: 定义一个响应式的数据
语法: const xxx = ref(initValue)
创建一个包含响应式数据的引用对象(reference对象,简称ref对象)。
JS中操作数据: xxx.value
模板中读取数据: 不需要.value,直接:<div>{{xxx}}</div>
备注:
接收的数据可以是:基本类型(值类型)、也可以是对象(引用类型)类型。

reactive
作用: 定义一个对象类型的响应式数据(基本类型不要用它,要用ref函数)
语法:const 代理对象= reactive(源对象)接收一个对象(或数组),返回一个代理对象(Proxy的实例对象,简称proxy对象)
reactive定义的响应式数据是“深层次的”,无论套多少层,都具备响应式

# 总结:
如果用基本数据类型:数字,字符串,布尔,用ref做响应式
如果是对象类型,用ref和reactive都可以,但是建议使用reactive
如果使用ref包裹对象类型,多了一层value

2、子组件

<template>
  <div class="hello">
    <h1>{{ msg }}</h1>
  </div>
</template>

<script >
export default {
  name: 'HelloWorld',
  setup(props, context, attrs, slots, emit) {
    console.log(props.msg)
    console.log(context)
  },
  props: ['msg']
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
h3 {
  margin: 40px 0 0;
}

ul {
  list-style-type: none;
  padding: 0;
}

li {
  display: inline-block;
  margin: 0 10px;
}

a {
  color: #42b983;
}
</style>

五、计算和监听属性

1、计算属性:computed、监听属性 watch

<template>
  <div class="home">
    <input type="text" v-model="name.firstName">
    <input type="text" v-model="name.lastName">
    <br>
    <input type="text" v-model="fullName">
    <button @click="age++">点我年龄加</button>
  </div>
</template>

<script>

// 导入
import {computed, watch, reactive, ref, watchEffect} from 'vue'

export default {
  setup() {
    // 计算属性:computed
    let name = reactive({
      firstName: 'liu',
      lastName: 'qz'
    })

    let fullName = computed({
      get() {
        return name.firstName + '-' + name.lastName
      },
      set(value) {
        const nameArr = value.split('-')
        name.firstName = nameArr[0]
        name.lastName = nameArr[1]
      }
    })

    let age = ref(19)

    // 监听属性
    // 监听基本类型
    watch(age, (newValue, oldValue) => {
      console.log(oldValue)
      console.log(newValue)
    })
    // 监听对象
    watch(() => name.firstName, (newValue, oldValue) => {
      console.log(oldValue)
      console.log(newValue)
    })
    // watchEffect函数
    watchEffect(() => {
      const x1 = age.value
      const x2 = name.firstName
      console.log('watchEffect配置的回调执行了')
    })

    return {name, fullName, age}
  }
}
</script>

补充:

在计算属性computed中,set(value)方法用于设置fullName的值,其中value是接收前端传进来要修改的值,fullName改变,firstName和lastName跟着改变。

六、生命周期

1、  Vue3.0中可以继续使用Vue2.x中的生命周期钩子,但有有两个被更名:

# vue2 生命周期---8个

# vue3 变了
	-把生命周期写下setup函数中
    	
        beforeDestroy改名为 beforeUnmount
        destroyed改名为 unmounted
        
        beforeCreate
        created
        beforeMount 
        mounted
        beforeUpdate
        updated
        beforeUnmount 
        unmounted

2、Vue3.0也提供了 Composition API 形式的生命周期钩子,与Vue2.x中钩子对应关系如下:

beforeCreate===>setup()
created=======>setup()
beforeMount ===>onBeforeMount
mounted=======>onMounted
beforeUpdate===>onBeforeUpdate
updated =======>onUpdated
beforeUnmount ==>onBeforeUnmount
unmounted =====>onUnmounted

3、示例

<template>
  <div class="home">
    <h1>首页</h1>
  </div>
</template>

<script>

import axios from "axios";
import {
  computed,
  watch,
  reactive,
  ref,
  watchEffect,
  onBeforeMount,
  onMounted,
  onBeforeUpdate,
  onUpdated,
  onBeforeUnmount,
  onUnmounted
} from 'vue'

export default {
  name: 'HomeView',
  setup() {

    // 第一个beforeCrete
    console.log('我是beforeCrete')

    // 第二个Creted
    let name = ref('lqz')
    console.log('Creted')
    // axios.get().then(res => {
    //   name.value = res.data.name
    // })

    // 直接启动定时器
    let t = setInterval(() => {
          console.log('lqz')
        }, 3000
    )
    // 第三个:onBeforeMount
    onBeforeMount(() => {
      console.log('挂载了')
    })

    onBeforeUnmount(() => {
      clearInterval(t)
      t = null

    })

    return {}

  },
}
</script>

七、torefs

作用:创建一个 ref 对象,其value值指向另一个对象中的某个属性。

语法:const name = toRef(person,'name')

应用: 要将响应式对象中的某个属性单独提供给外部使用时。

扩展:toRefs 与toRef功能一致,但可以批量创建多个 ref 对象,语法:toRefs(person)

<template>
  <div className="home">
    <h1>首页</h1>
    {{ name }}---{{ age }}
  </div>
</template>

<script>

import {
  reactive,
  toRefs
} from 'vue'

export default {
  name: 'HomeView',
  setup() {
    let data = reactive({
      name: 'lqz',
      age: 18
    })
    return {...toRefs(data)}
  },
}
// 对象的解压
let data = {'name': 'lqz', age: 19}
let dict = {...data, hobby: '篮球'}
console.log(dict)
</script>

补充:

torefs的作用:data里面定义的数据,可以直接引用,而不是data.xx这样

八、vue3 setup写法

# 以后vue3推荐,把setup函数的代码,直接写在script中
<script setup>
定义变量
写函数
不用return,在html中直接使用
</script>

# 使用组件,直接导入,不需要配置,直接用即可
import HelloWorld from "../components/HelloWorld.vue";
在html中直接用:<HelloWorld msg="NB"></HelloWorld>

# 自定义属性,在子组件中接收
    <script setup>
    defineProps({
      msg: {
        type: String,
        required: true
      }
    })
    </script>

  

posted @ 2023-10-07 14:43  凡人半睁眼  阅读(13)  评论(0编辑  收藏  举报