setup

setup 函数是一个新的组件选项。作为在组件内使用 Composition API 的入口点。

创建组件实例,然后初始化 props ,紧接着就调用 setup 函数。从生命周期钩子的视角来看,它会在 beforeCreate 钩子之前被调用。

1、不要解构 props 对象,那样会使其失去响应性
2、this 在 setup() 中不可用

如果 setup 返回一个对象,则对象的属性可以在组件模板中使用。

<template>
  <h1>{{ msg }}</h1>
  <button @click="change">count is: {{ count }}</button>
  <p>Edit <code>components/HelloWorld.vue</code> to test hot module replacement.</p>
</template>

<script>
export default {
  name: 'HelloWorld',
  props: {
    msg: String
  },
  setup(){
    let count = 0
    const change = () => count++
    return { count, change }
  }
}
</script>

ref

Vue 本身已经有 “ref” 的概念了。但只是为了在模板中获取 DOM 元素或组件实例 (“模板引用”)。新的 ref 系统同时用于逻辑状态和模板引用。

接受一个参数值并返回一个响应式且可改变的 ref 对象。ref 对象拥有一个指向内部值的单一属性 .value

当 ref 创建的属性在模板中使用时,它会自动解开,无需在模板内额外书写 .value

<template>
  <h1>{{ msg }}</h1>
  <button @click="change">count is: {{ count }}</button>
  <p>Edit <code>components/HelloWorld.vue</code> to test hot module replacement.</p>
</template>

<script>
import { ref } from 'vue'
export default {
  name: 'HelloWorld',
  props: {
    msg: String
  },
  setup(){
    let count = ref(0)
    const change = () => count.value++
    return { count, change }
  }
}
</script>

reactive

接收一个普通对象然后返回响应式的对象。等同于 2.x 的 Vue.observable()

<template>
  <h1>{{ msg }}</h1>
  <button @click="change">count is: {{ state.count }}</button>
  <p>Edit <code>components/HelloWorld.vue</code> to test hot module replacement.</p>
</template>

<script>
import { ref, reactive } from 'vue'
export default {
  name: 'HelloWorld',
  props: {
    msg: String
  },
  setup(){
    let state = reactive({count: 0})
    const change = () => state.count++
    return { state, change }
  }
}
</script>

watch

watch 需要侦听特定的数据源,并在回调函数中执行副作用。默认情况是懒执行的,也就是说仅在侦听的源变更时才执行回调。

侦听单个数据源

<template>
  <h1>{{ msg }}</h1>
  <button @click="change">count is: {{ state.count }}</button>
  <p>Edit <code>components/HelloWorld.vue</code> to test hot module replacement.</p>
</template>

<script>
import { ref, reactive, watch } from 'vue'
export default {
  name: 'HelloWorld',
  props: {
    msg: String
  },
  setup(){
    let state = reactive({count: 0})
    watch(() => state.count, (newCount, oldcount) => {
      console.log(newCount, oldcount, 'count发生改变')
    })
    const change = () => state.count++
    return { state, change }
  }
}
</script>

侦听多个数据源

<template>
  <h1>{{ msg }}</h1>
  <button @click="change">count is: {{ state.count }}</button>
  <p>Edit <code>components/HelloWorld.vue</code> to test hot module replacement.</p>
</template>

<script>
import { ref, reactive, watch } from 'vue'
export default {
  name: 'HelloWorld',
  props: {
    msg: String
  },
  setup(){
    let state = reactive({count: 0})
    watch(state, (newState) => {
      console.log(newState, 'state发生改变')
    })
    const change = () => state.count++
    return { state, change }
  }
}
</script>

watchEffect

立即执行传入的一个函数,并响应式追踪其依赖,并在其依赖变更时重新运行该函数。

与watch的区别

1、watch是需要传入需要侦听特定的数据源,而watchEffect是自动收集需要侦听特定的数据源。
2、watch可以访问侦听状态变化前后的值,而watchEffect没有。
3、watch是属性改变的时候执行,而watchEffect是默认会执行一次,然后属性改变也会执行。

<template>
  <h1>{{ msg }}</h1>
  <button @click="change">count is: {{ state.count }}</button>
  <p>Edit <code>components/HelloWorld.vue</code> to test hot module replacement.</p>
</template>

<script>
import { ref, reactive, watch, watchEffect } from 'vue'
export default {
  name: 'HelloWorld',
  props: {
    msg: String
  },
  setup(){
    let state = reactive({count: 0})
    watchEffect(() => {
      console.log(state.count, 'count改变')
    })
    const change = () => state.count++
    return { state, change }
  }
}
</script>

computed

传入一个 getter 函数,返回一个默认不可手动修改的 ref 对象。或者传入一个拥有 get 和 set 函数的对象,创建一个可手动修改的计算状态。

<template>
  <h1>{{ text }}</h1>
  <button @click="change">count is: {{ state.count }}</button>
  <p>Edit <code>components/HelloWorld.vue</code> to test hot module replacement.</p>
</template>

<script>
import { ref, reactive, watch, watchEffect, computed } from 'vue'
export default {
  name: 'HelloWorld',
  props: {
    msg: String
  },
  setup(props){
    let state = reactive({count: 0})
    let text = computed(() => {
      return props.msg.split('').reverse().join('')
    })
    const change = () => state.count++
    return { state, change, text }
  }
}
</script>

全选操作

<template>
  <input type="checkbox" id="all" v-model="checkedAll">
  <label for="all">全部选择</label>
  <div></div>
  <input type="checkbox" id="jack" value="Jack" v-model="checkedNames">
  <label for="jack">Jack</label>
  <input type="checkbox" id="john" value="John" v-model="checkedNames">
  <label for="john">John</label>
  <input type="checkbox" id="mike" value="Mike" v-model="checkedNames">
  <label for="mike">Mike</label>
  <br>
  <span>Checked names: {{ checkedNames }}</span>
</template>

<script>
import { ref, reactive, watch, watchEffect, computed } from 'vue'
export default {
  name: 'HelloWorld',
  props: {
    msg: String
  },
  setup(props){
    let checkedNames = ref([])
    let checkedAll = computed({
      get () {
        return checkedNames.value.length === 3
      },
      set (value) {
        if (value) {
          checkedNames.value = ['Jack', 'John', 'Mike']
        } else {
          checkedNames.value = []
        }
      }
    })
    return { checkedNames, checkedAll }
  }
}
</script>

改成通过reactive创建响应式

<template>
  <input type="checkbox" id="all" v-model="checkedAll">
  <label for="all">全部选择</label>
  <div></div>
  <input type="checkbox" id="jack" value="Jack" v-model="state.checkedNames">
  <label for="jack">Jack</label>
  <input type="checkbox" id="john" value="John" v-model="state.checkedNames">
  <label for="john">John</label>
  <input type="checkbox" id="mike" value="Mike" v-model="state.checkedNames">
  <label for="mike">Mike</label>
  <br>
  <span>Checked names: {{ state.checkedNames }}</span>
</template>

<script>
import { ref, reactive, watch, watchEffect, computed } from 'vue'
export default {
  name: 'HelloWorld',
  props: {
    msg: String
  },
  setup(props){
    let state = reactive({checkedNames: []})
    let checkedAll = computed({
      get () {
        return state.checkedNames.length === 3
      },
      set (value) {
        if (value) {
          state.checkedNames = ['Jack', 'John', 'Mike']
        } else {
          state.checkedNames = []
        }
      }
    })
    return { state, checkedAll }
  }
}
</script>

toRef

toRef 可以用来为一个 reactive 对象的属性创建一个 ref。这个 ref 可以被传递并且能够保持响应性。

<template>
  <input type="checkbox" id="all" v-model="checkedAll">
  <label for="all">全部选择</label>
  <div></div>
  <input type="checkbox" id="jack" value="Jack" v-model="checkedNames">
  <label for="jack">Jack</label>
  <input type="checkbox" id="john" value="John" v-model="checkedNames">
  <label for="john">John</label>
  <input type="checkbox" id="mike" value="Mike" v-model="checkedNames">
  <label for="mike">Mike</label>
  <br>
  <span>Checked names: {{ checkedNames }}</span>
</template>

<script>
import { ref, reactive, watch, watchEffect, computed, toRef } from 'vue'
export default {
  name: 'HelloWorld',
  props: {
    msg: String
  },
  setup(props){
    let state = reactive({checkedNames: []})
    let checkedAll = computed({
      get () {
        return state.checkedNames.length === 3
      },
      set (value) {
        if (value) {
          state.checkedNames = ['Jack', 'John', 'Mike']
        } else {
          state.checkedNames = []
        }
      }
    })
    let checkedNames = toRef(state, 'checkedNames')
    return { checkedNames, checkedAll }
  }
}
</script>

不要解构 state 对象,那样会使其失去响应性

toRefs

把一个响应式对象转换成普通对象,该普通对象的每个 property 都是一个 ref ,和响应式对象 property 一一对应。

<template>
  <input type="checkbox" id="all" v-model="checkedAll">
  <label for="all">全部选择</label>
  <div></div>
  <input type="checkbox" id="jack" value="Jack" v-model="checkedNames">
  <label for="jack">Jack</label>
  <input type="checkbox" id="john" value="John" v-model="checkedNames">
  <label for="john">John</label>
  <input type="checkbox" id="mike" value="Mike" v-model="checkedNames">
  <label for="mike">Mike</label>
  <br>
  <span>Checked names: {{ checkedNames }}</span>
</template>

<script>
import { ref, reactive, watch, watchEffect, computed, toRef, toRefs } from 'vue'
export default {
  name: 'HelloWorld',
  props: {
    msg: String
  },
  setup(props){
    let state = reactive({checkedNames: []})
    let checkedAll = computed({
      get () {
        return state.checkedNames.length === 3
      },
      set (value) {
        if (value) {
          state.checkedNames = ['Jack', 'John', 'Mike']
        } else {
          state.checkedNames = []
        }
      }
    })
    let stateAsRefs = toRefs(state)
    return { ...stateAsRefs, checkedAll }
  }
}
</script>
Logo

前往低代码交流专区

更多推荐