关于vue.js:Vue3正确的打开方式下

36次阅读

共计 5284 个字符,预计需要花费 14 分钟才能阅读完成。

1. 计算属性(computed)

computed 的返回值是一个响应式的 ref 对象

import {ref, computed} from 'vue'

const count = ref(10)

// 写法一:默认返回 getter 函数 返回值为一个只读的 ref 对象
const doubleCount = computed(() => count.value * 2)

// 因为返回值为 ref 对象 取值须要拿它的 value
console.log(doubleCount.value) // 20

// 留神:这里控制台会报正告,因为咱们只设置了 getter 函数
doubleCount.value = 20 // warn:readonly(只读)属性 不可批改

// 写法二:带有 getter 和 setter 函数
const doubleCount = computed({get: () => count.value * 2,
  set: (val) => count.value = val - 2
})

console.log(doubleCount.value) // 20

//  不会报正告,因为咱们手动设置了 setter 函数
doubleCount.value = 10  // 批改 doubleCount 的值 触发 set 函数

// 所以 count 的值为 10 - 2 = 8
console.log(count.value) // 8

2. 响应式侦听(watch)

①. 监听根本数据类型:

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

setup() {

  // 写法一:监听一个一般的值
  const data = reactive({count: 100})
  // 第一个参数写成函数
  watch(() => data.count, (newVal, oldVal) => {console.log(newVal, 'newVal')
    console.log(oldVal, 'oldVal')
  })

  // 写法二:监听 ref 对象
  const count = ref(100)
  // 第一个参数写成函数
  watch(() => count, (newVal, oldVal) => {console.log(newVal, 'newVal')
    console.log(oldVal, 'oldVal')
  })

  // 写法三:同时监听多个值
  const num = ref(200)
  // 第一个参数写成数组模式,代表要监听的值
  watch([count, num], (newVals, oldVals) => {// 这里打印的是一个数组 值别离对应:[count, num]
    console.log(newVals, 'newVals')
    console.log(oldVals, 'oldVals')
  })

  count.value = 300 // newVals: [300, 200]   oldVals: [100, 200]
  num.value = 400   // newVals: [300, 400]   oldVals: [300, 200]
}

②. 监听援用数据类型:

import {watch, reactive} from 'vue'

setup() {const list = reactive([1, 2, 3, 4, 5])
  // 这里须要对援用数据类型进行拷贝
  watch(() => [...list], (newVal, oldVal) => {console.log(newVal, 'newVal')
    console.log(oldVal, 'oldVal')
  })

  list.push(6) // newVal: [1, 2, 3, 4, 5, 6]  oldVal: [1, 2, 3, 4, 5]
}
不出意外,vue3 的 watch 同样反对 deep、immediate 属性,只是用法有所扭转
const userInfo = reactive({
  username: 'kyrie irving',
  email: '123@qq.com',
  like: {isBasketball: true}
})

// 传入一个对象作为第三个参数 可开启 deep/immediate
watch(() => userInfo, (newVal, oldVal) => {console.log(newVal.like.isBasketall)
  console.log(oldVal.like.isBasketall)
}, {deep: true})

// 批改状态深层属性的值
userInfo.like.isBasketball = false // 打印日志: false, false
看到日志输入两个 false 是不是感觉哪里不对劲?
留神:如果你想要在批改后的状态中拿到上一个状态里的值,须要深拷贝
起因:watch 的返回值是:以后状态(newVal)和上一个状态的援用(oldVal)
// 正确写法(对援用数据类型进行深拷贝)(这里应用 vue 官网举荐的 lodash 深拷贝办法,当然你也能够手写(手动狗头)import _ from 'lodash'

watch(() => _.cloneDeep(userInfo), (newVal, oldVal) => {console.log(newVal.like.isBasketall)
  console.log(oldVal.like.isBasketall)
})

// 批改状态深层属性的值 这里就能够拿到上一个状态的值啦
userInfo.like.isBasketball = false // 打印日志: false, true

3. 组合式 API(外围知识点)

假如咱们要开发一个 todoList,那么在 vue2 的选项式(options)API 中,代码大抵长这样:
export default {components: ['Header', 'List', 'Footer'],

  props: {
    item: {
      type: Object,
      required: true,
      default: () => {},
    }
  },

  data() {
    return {value: '',}
  },

  computed: {finallyValue() {}},

  methods: {addTodo(data) {}},

  mounted() {this.init()
  }
}

很显著能够看到,咱们写的 代码被瓜分 到(data,computed, methods, mounted…)外面,当组件小的时候还好,但当咱们开发一个 大型组件 的时候,就会发现咱们的组件变得 难以保护

不晓得大家有没有这种体验:当咱们的组件 代码行数太多 时,咱们时常须要一直地 高低‘跳转’编译器,找到相干的代码块去浏览或编写,这显然开发体验不是很好。

要是有一种货色能够解决这种开发中因为 代码太过于碎片化 ,而且 逻辑不好复用 的问题,是不是能够进步咱们的 开发效率 ?而这正是 vue3 推出 组合式 API呈现的起因。

在 Vue3 正确的打开方式(上)里,咱们曾经用到组合式 API 了,定义响应式对象(ref, reactive)…

补充一些对于 生命周期 props的常识 …

生命周期(vue3 将不再须要:beforeCreate、created,起因看下文)
// vue3 中为了性能,很多 API(办法)都反对 Tree Shaking 
// 所以须要从 vue 中显式导入,生命周期也不例外
import {onBeforeMount,      (对应 beforeMount)
  onMounted,          (对应 mounted)
  onBeforeUpdate,     (对应 beforeUpdate)
  onUpdated,          (对应 updated)
  onBeforeUnmount,    (对应 beforeUnmount)
  onUnmounted,        (对应 unmounted)
  onErrorCaptured,    (对应 errorCaptured)   根本不必
  onRenderTracked,    (对应 renderTracked)   根本不必
  onRenderTriggered   (对应 renderTriggered) 根本不必
} from 'vue'

// 第一个参数 props,第二个参数为上下文(包含 slots,attrs,emit)setup(props, context) {

  // 用法跟 vue 相似,不一样的中央在于它承受一个回调函数,在钩子被组件调用时执行
  onMounted(() => {console.log('mouted')
  }),
  
  // 其余的钩子相似,这里就不一一列举了
  ...
}

tips:vue3 的 setup 是围绕 beforeCreatecreated生命钩子运行的,所以你不须要 显式地定义 这两个钩子函数,通俗易懂就是说 之前在这两个钩子里编写的代码 当初你都应该 编写在 setup 函数 中。

props(响应式援用)

import {toRefs} from 'vue'

// 接管跟 vue2 一样 可进行类型校验和默认值设置
props: {
  username: {
    type: String,
    default: ''
  },
  email: {
    type: String,
    default: ''
  }
}

// 第一个参数 props,第二个参数为上下文(包含 slots, attrs, emit)// 所以你能够应用解构的写法,须要留神的是:attrs 和 slots 是有状态的对象
// 所以你应该以 attrs.x 或 slots.xx 来应用,且它们是非响应式的。setup(props, { slots, attrs, emit}) {

 // 留神:解构会失落响应式
  const {username, email} = props
  
  console.log(username, email)

  // 须要调用 toRefs()解决响应式失落问题
  const {username, email} = toRefs(props)
}

4. Provide / Inject

provide(name, value) name(String 类型)
inject(name, 默认值(可选)) inject 的 name 和 provide 的 name 要绝对应

Parent.vue 父组件

<template>
  <div>
    <h1>App</h1>
    <p>App 的 count:{{count}}</p>
    <p>App 的用户名:{{userInfo.username}}</p>
    // 子孙组件
    <Child />
  </div>
</template>

<script>
// 先引入 provide
import {provide} from 'vue'

  setup() {

    // 倡议把 provide 的状态转换为响应式(ref / reactive)const count = ref(100);

    const userInfo = reactive({
      username: "kyrie",
      email: "123@qq.com",
    });

    // 如果须要批改 provide 外面的状态 举荐在父组件注入批改状态的办法
    const changeCount = () => {count.value++;};

    const changeUsername = () => {userInfo.username = "wen";};

    // 为了防止 inject 组件批改 provide 的状态 应用 readonly 确保数据不被 inject 组件批改
    provide("count", readonly(count));
    provide("userInfo", readonly(userInfo));

    provide("changeCount", changeCount);
    provide("changeUsername", changeUsername);
  }
</script>

Child.vue 组件

<template>

  <h2>Child</h2>
  <p>inject 的 count:{{count}}</p>
  <p>inject 的用户名:{{userInfo.username}}</p>
  <p>inject 的邮箱:{{userInfo.email}}</p>
  
  // 调用 inject 的 changeCount 办法批改 count
  <button @click="changeCount">count++</button> &nbsp;
  // 调用 inject 的 changeUsername 办法批改用户名
  <button @click="changeUsername"> 批改用户名 </button>
  
</template>

<script>
import {inject} from "vue";
export default {setup(props, context) {
    // 注入 count 并设置 count 的默认值为 0
    const count = inject("count", 0);
    // 注入 userInfo 并设置 userInfo 的默认值为 0
    const userInfo = inject("userInfo", {});
    // 注入批改 count 的办法
    const changeCount = inject("changeCount");
    // 注入批改 userInfo 的办法
    const changeUsername = inject("changeUsername");
    return {
      count,
      userInfo,
      changeCount,
      changeUsername,
    };
  },
};
</script>

以上就是 Vue3罕用 的也算比拟 外围 的 API 了,如果你有什么纳闷或者问题,欢送在下方留言哦 …

正文完
 0