Setup  vue 3.0

  •  setup是一个新的组件选项,作为组件中使用组合API的起点。 
  • 从组件生命周期来看,它的执行在组件实例创建之前vue2.x的beforeCreate执行。
  • 这就意味着在setup函数中this 还不是组件实例,this此时是undefined
  • 在模版中需要使用的数据和函数,需要在setup返回。  

    <template>
      <div class="container">
        <h1 @click="say()">{{msg}}</h1>
      </div>
    </template>
    <script>
    export default {
      setup () {
        console.log('setup执行了')
        console.log(this)
        // 定义数据和函数
        const msg = 'hi vue3'
        const say = () => {
          console.log(msg)
        }
    
        return { msg , say}
      },
      beforeCreate() {
        console.log('beforeCreate执行了')
        console.log(this)
      }
    }
    </script>

    总结:setup组件初始化之前执行,它返回的数据和函数可在模版使用

Setup  vue 3.2

script setup 语法糖

<script setup></script>

1. 属性和方法无需返回,直接使用

在添加了setup的script标签中,我们不必声明和方法,这种写法会自动将所有顶级变量、函数,均会自动暴露给模板(template)使用 。

<template>
    <div>
        // 调用方法
        <button @click='changeName'>name</button>  
    </div>
</template>

<script setup>
import { ref} from 'vue'

  const name= ref('Jerry')

  // 声明method方法
  const changeName = () => {
    name.value = 'Tom'
  }  
</script>

reactivecomputed, 也一样可以使用: 

<template>
	<div>{{msg}}</div>
	<div>{{obj.a}}</div>
	<div>{{sum}}</div>
</template>

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

const msg = ref('hello vue3');

const obj = reactive({
	a: 1,
	b: 2
})

const sum = computed(() => {
	return obj.a + 3;
});
</script>

 2. 组件自动注册

<template>
	<Child />
</template>

<script setup>
import Child from '@/components/Child.vue'
</script>

组合API-父子通讯  vue3.0

父传子:

<template>
  <div class="container">
    <h1>父组件</h1>
    <p>{{money}}</p>
    <hr>
    <Son :money="money" />
  </div>
</template>
<script>
import { ref } from 'vue'
import Son from './Son.vue'
export default {
  name: 'App',
  components: {
    Son
  },
  // 父组件的数据传递给子组件
  setup () {
    const money = ref(100)
    return { money }
  }
}
</script>
<template>
  <div class="container">
    <h1>子组件</h1>
    <p>{{money}}</p>
  </div>
</template>
<script>
import { onMounted } from 'vue'
export default {
  name: 'Son',
  // 子组件接收父组件数据使用props即可
  props: {
    money: {
      type: Number,
      default: 0
    }
  },
  setup (props) {
    // 获取父组件数据money
    console.log(props.money)
  }
}
</script>

子传父:

<template>
  <div class="container">
    <h1>父组件</h1>
    <p>{{money}}</p>
    <hr>
+    <Son :money="money" @change-money="updateMoney" />
  </div>
</template>
<script>
import { ref } from 'vue'
import Son from './Son.vue'
export default {
  name: 'App',
  components: {
    Son
  },
  // 父组件的数据传递给子组件
  setup () {
    const money = ref(100)
    const updateMoney = (newMoney) => {
      money.value = newMoney
    }
    return { money , updateMoney}
  }
}
</script>
<template>
  <div class="container">
    <h1>子组件</h1>
    <p>{{money}}</p>
    <button @click="changeMoney">花50元</button>
  </div>
</template>
<script>
export default {
  name: 'Son',
  // 子组件接收父组件数据使用props即可
  props: {
    money: {
      type: Number,
      default: 0
    }
  },
  // props 父组件数据
  // emit 触发自定义事件的函数
  setup (props, {emit}) {
    // 获取父组件数据money
    console.log(props.money)
    // 向父组件传值
    const changeMoney = () => {
      // 消费50元
      // 通知父组件,money需要变成50
      emit('change-money', 50)
    }
    return {changeMoney}
  }
}
</script>

扩展:

  • 在vue2.x的时候 .sync 除去v-model实现双向数据绑定的另一种方式
<Son :money='money' @update:money="fn"  />
<Son :money.sync='money'  />
  • 在vue3.0的时候,使用 v-model:money="money" 即可
<Son v-model:money="money" />

总结:

  • 父传子:在setup种使用props数据 setup(props){ props就是父组件数据 }
  • 子传父:触发自定义事件的时候emit来自 setup(props,{emit}){ emit 就是触发事件函数 }
  • 在vue3.0中 v-model 和 .sync 已经合并成 v-model 指令

组合API-父子通讯  vue3.2

因为没有了setup函数,那么props,emit怎么获取呢

setup script语法糖提供了新的API来供我们使用

defineProps

如果只是单纯在 template 里使用,那么其实就这么简单定义就可以了:

import { defineProps } from 'vue'

defineProps(['name', 'userInfo', 'tags'])

如果 script 里的方法要拿到 props 的值,你也可以使用字面量定义:

const props = defineProps(['name', 'userInfo', 'tags'])

console.log(props.name)

如果不显性的指定 prop 类型的话,很容易在协作中引起程序报错,所以跟我们平时定义 prop 类型时一样, Vue 会通过 instanceof 来进行 类型检查 。

使用这种方法,需要通过一个 “对象” 入参来传递给 defineProps,比如:

defineProps({
  name: {
    type: String,
    required: false,
    default: 'Petter',
  },
  userInfo: Object,
  tags: Array,
})

父传子:

<template>
  <div class="container">
    <h3>我是父组件</h3>
    <Son :name="name"></Son>
  </div>
</template>

<script setup>
  import Son from "./Son"
  import {ref} from "vue"
  let name = ref("张三")
</script>

子组件代码:

<template>
  <div>
    我是子组件{{name}} 
  </div>
</template>

<script setup>
  import {defineProps} from "vue"

  defineProps({
   name:{
     type:String,
     default:"我是默认值"
   }
 })
</script>

defineEmits

defineEmit 也是一个方法,它接受的入参格式和标准组件的要求是一致的。

由于 emit 并非提供给模板直接读取,所以需要通过字面量来定义 emits,最基础的用法也是传递一个 string[] 数组进来,把每个 emit 的名称作为数组的 item 。

重复定义的话,事件就会不生效。

// 获取 emit
const emit = defineEmit(['chang-name'])

// 调用 emit
emit('chang-name', 'Tom')

子传父:

<template>
  <div>
    我是子组件{{name}}
    <button @click="ziupdata">按钮</button>
  </div>
</template>

<script setup>
  import {defineEmits} from "vue"

  //自定义函数,父组件可以触发
  const em=defineEmits(["updata"])
  const ziupdata=()=>{
    em("updata","我是子组件的值")
  }

</script>

父组件代码:

<template>
  <div class="container">
    <h3>我是父组件</h3>
    <Son @updata="updata"></Son>
  </div>
</template>

<script setup>
  import Son from "./Son"
  
  const updata = (data) => {
    console.log(data); //我是子组件的值
  }
</script>

defineExpose

  • 在标准组件写法里,子组件的数据都是默认隐式暴露给父组件的,但在 script-setup 模式下,所有数据只是默认 return 给 template 使用,不会暴露到组件外,所以父组件是无法直接通过挂载 ref 变量获取子组件的数据。
  • 如果要调用子组件的数据,需要先在子组件显示的暴露出来,才能够正确的拿到,这个操作,就是由 defineExpose 来完成。 
<template>
  <div class="list-card">
    这是子组件
  </div>
</template>
<script setup>
    import { defineExpose, reactive, ref } from 'vue'
    let sonNum = ref(0)
    let sonName = reactive({
      name: '小明'
    })
    defineExpose({
      sonNum,
      sonName
    })
</script>

父组件代码:

<template>
    <List ref="sonRef"></List>
    <button @click="getSonData">获取子组件暴漏的值</button>
</template>
<script setup>
    import List from '../components/list.vue'
    import { ref } from 'vue'
    const sonRef = ref()
    function getSonData() {
      console.log('子组件中ref暴漏的数值', sonRef.value.sonNum) 
      // 子组件中ref暴漏的数值 0
      console.log('子组件中reactive暴漏的字符串', sonRef.value.sonName.name) 
      // 子组件中reactive暴漏的字符串 小明
    }
</script>

vue指令变化

v-text,v-html,v-show,v-on,v-bind,v-slot,v-pre,v-cloak,v-once,v-is都和之前用法一样

v-if  v-for 指令

vue3.0中 

 vue3.2中

 v-memo 指令

 v-memo 是一个vue3.2 新增的自定义指令,用于提升渲染性能。

记忆模板的子树(子组件或者子元素),用数组存储,被记忆的在下次虚拟dom渲染的时候如果没有发生过任何改变,则跳过这个子组件或子元素,不会触发更新渲染

<div ref="parent"  v-memo="[componentA, componentB]">
    <!-- 倘若被记忆的 componentA和componentB 其中一个或全部
    没有任何更改,则生成这个parent节点不会触发内部节点的更新-->
     <componentA />
     <componentB />
<div />

vue3.x中不支持filters过滤器的解决方法

在3.x中,过滤器被删除,不再受支持。相反,我们建议用方法调用或计算属性替换它们。

 使用计算属性

Logo

前往低代码交流专区

更多推荐