Skip to content

vue3 语法

template 变动

现在 template 标签下 可以写多个根标签,不在是只能写一个根标签

vue
<template>
  <div>dsad</div>
  <div>dsad</div>
</template>

setup 语法

setup 是vue3 新增语法糖,简化 js

vue
<script setup lang="ts">

</script>

使用了setup 后,当前组件页面内,使用外部组件无需使用 export default components 属性声明,在setup 内的变量会全部自动导出

vue2 写法

vue
<template>
  <hello-world msg="dsads"></hello-world>
</template>
<script lang="ts">
import HelloWorld from "./components/HelloWorld.vue";
export default {
  components:{
    HelloWorld
  }
}
</script>

vue3 写法

vue
<template>
  <hello-world msg="dsads"></hello-world>
</template>

<script setup lang="ts">
import HelloWorld from "./components/HelloWorld.vue";
</script>

ref

ref 是vue3 声明响应式数据的方式 由于vue3 不推荐使用

export default 方式,改为以下方式

vue
<template>
  <hello-world :msg="num"></hello-world>
  <button @click="change">change</button>
</template>

<script setup lang="ts">

import HelloWorld from "./components/HelloWorld.vue";
import {ref} from "vue";
// 使用 ref 绑定数据
let num = ref<string>("111")
const change =()=>{
  num.value= "dsadsa"
}

</script>

ref 适用了简单数据类型,并且如果要更改ref 绑定的数据,需要 num.value= "dsadsa"方式,才能动态更改

ref 也可以用于复杂类型,源码中进行了判断,如果是复杂数据类型会转换成 reactive 类型

reactive

也是声明响应式数据的方式

vue
<template>
  <button @click="change">change</button>
  <div>{{list}}</div>
</template>

<script setup lang="ts">
import {ref,reactive} from "vue";

let list =  reactive<number[]>([1,2,34,5]);
const change =()=>{
  list = [2]
  console.log(list)
}
console.log(list)

</script>

修改响应式数据为数组时,可以直接修改,不需要再调用value 属性

但是当修改值为数组时,会破坏响应数据,从而变成普通数据

解决方法1

vue
<template>
  <button @click="change">change</button>
  <div>{{list}}</div>
</template>

<script setup lang="ts">
import {ref,reactive} from "vue";

type o ={
  list:number[]
}

let list =  reactive<o>({
  list:[1,2,34,5]
});
const change =()=>{
  list.list = [2]
  console.log(list)
}
console.log(list)

</script>

通过定义一个临时类型对象来赋值

解决方法2

vue
<template>
  <button @click="change">change</button>
  <div>{{list}}</div>
</template>

<script setup lang="ts">
import {ref,reactive} from "vue";


let list =  reactive<number[]>([1,2,34,5]);
const change =()=>{
  let a = [2]
  list.push(...a)
  console.log(list)
}
console.log(list)

</script>

computed

计算属性,当函数内部使用到的外部变量发生变动时,就会除非计算属性方法

js
totalPrice = computed(() => {
  let $total = 0
  shopList.forEach(e => {
    $total += (e.price * e.total)
  })
  return $total;
})

watch

监听变量

vue
<template>
  <input type="text" v-model="obj">
</template>

<script setup lang="ts">
import {ref, reactive, watch} from "vue";

let obj=  ref(111)

watch(obj,(newVal,oldVal)=>{
  console.log("新值:===",newVal);
  console.log("旧值:===",oldVal);
})

</script>

这样当我们修改obj 时,就会出发监听函数,

但是当我们监听复杂类型时,ref 绑定的数据,是不会监听深层次的值的,

例如

vue
let obj=  ref({
	name:'zs'
})

vue 并不会帮我们监听name的值,

需要开启深层次监听 deep:true

vue
<template>
  <input type="text" v-model="obj.name">
</template>

<script setup lang="ts">
import {ref, reactive, watch} from "vue";

let obj=  ref({
  name:"zs"
})

watch(obj,(newVal,oldVal)=>{
  console.log("新值:===",newVal);
  console.log("旧值:===",oldVal);
},{deep:true})

</script>

如果使用reactive 来绑定,则不需要开启deep:true

注意,如果监听对象的话,会导致旧值与新值相同,这不是bug,这是因为vue 绑定的是数据的引用地址原因

监听对象中的某个值

vue
<template>
  <input type="text" v-model="obj.name">
</template>

<script setup lang="ts">
import {ref, reactive, watch} from "vue";

let obj=  ref({
  name:"zs"
})

// 使用监听函数,返回需要监听的值
watch(()=>obj.value.name,(newVal,oldVal)=>{
  console.log("新值:===",newVal);
  console.log("旧值:===",oldVal);
})

</script>

生命周期函数

vue
<script setup lang="ts">
import {onMounted} from "vue";


// 类比vue2 中的 mounted() 函数
onMounted(()=>{
  
})

</script>

defineProps

props 属性,父组件向子组件传值使用了 defineProps

vue
<!--父组件-->
<template>
  <div class="layout">
    <Menu :name="name"></Menu>
    <div class="layout-right">
      <Header></Header>
      <Content></Content>
    </div>
  </div>
</template>

<script setup lang="ts">
import Content from './Content/index.vue'
import Header from './Header/index.vue'
import Menu from './Menu/index.vue'

import {reactive, ref} from 'vue'

let name =  ref<string>("zs")

</script>
vue
<!--子组件-->
<template>
  <div class="menu">
    Menu
    <div>
      {{name}}
    </div>
  </div>
</template>

<script setup lang="ts">

type Props={
  name:string
  
}
// 使用 defineProps 泛型来声明props 的类型
defineProps<Props>()

</script>
vue
<!--子组件-->
<template>
  <div class="menu">
    Menu
    <div>
      {{name}}
    </div>
  </div>
</template>

<script setup lang="ts">

type Props={
  name:string
 data?:number[] // 加问号,表示可以不传递data props值,但是此时没有默认值  
}
// 使用 withDefaults来规定默认值,如果类型是对象,则使用函数返回值形式
withDefaults(defineProps<Props>(),{
    data:()=>[1233,54,768]
})


</script>

defineEmits

事件派发,可以有子组件触发事件,传递给父组件,也可以从子组件传值给父组件

vue
<template>
  <div class="menu">
    Menu
    <div>
      {{name}}
    </div>
    <div>
      <button @click="onClick">派发</button>
    </div>
  </div>
</template>

<script setup lang="ts">
import {reactive} from "vue";
    
// defineEmits  是一个函数,接收一个数组,数组中就是传递的事件名称,返回值是 派发对象
const emits =  defineEmits(['on-click'])
let list = reactive([1,23,5])
const onClick = ()=>{
  // 触发子组件事件时,给父组件传递一个事件名称,并且传值给父组件
  emits('on-click',list)
}
</script>
vue
<template>
  <div class="layout">
     <!-- 父组件需要使用 @事件名称 来绑定事件 -->
    <Menu :name="name" @on-click="getData"></Menu>
    <div class="layout-right">
      <Header></Header>
      <Content></Content>
    </div>
  </div>
</template>

<script setup lang="ts">
import Content from './Content/index.vue'
import Header from './Header/index.vue'
import Menu from './Menu/index.vue'

import {reactive, ref} from 'vue'

let name =  ref<string>("zs")

// 子组件派发的事件,参数为子组件传递的参数
const getData = (list:number[])=>{
  console.log(list)
}
</script>

样式穿透

在使用ui库时,可能需要修改原本组件的样式,则,可以使用

css
:deep(.ui-sdsa){
    color:red
}