vue3 组合式API

 

 

# 组合式API

Vue3.0在原来2.0版本基础上进行升级的时候,进行语法上的扩展与兼容。

 

快速使用

src/views/Group.vue,代码:

<script setup>

import {reactive} from "vue";
//students:[] ,//学生数据
let students = reactive({
  data: [
    {"id":1,"name":"小明","age":17},
    {"id":2,"name":"小明","age":17},
  ]
});

const add_student = ()=>{
  //添加学生

}

const get_student =()=>{
  //获取学生
}

const del_student =()=>{

}
//courses:[] ,//课程数据

let courses = reactive({
  data: [
    {"id":1, "name": "python"},
    {"id":2, "name": "java"},
  ]
});

const add_course = ()=>{
  //添加课程
}
const get_course=(id)=>{
  //获取课程信息
}
const del_course =()=>{
  //删除课程
}

</script>

<template>

</template>

<style scoped>


</style>

 

 

 

做拆分

src/views/Group.vue,代码:

<script setup>

import student from "../api/student.js";
import {add_student} from "../api/student.js";
import course, {add_course} from "../api/course.js";
</script>

<template>
  <button @click="add_student">添加学生</button>
  <ul>
    <li v-for="student in student.data">{{student}}</li>
  </ul>
  <button @click="add_course">添加课程</button>
  <ul>
    <li v-for="course in course.data">{{course}}</li>
  </ul>
</template>

<style scoped>


</style>

 

 

 src/api/courses.js,代码:

import {reactive} from "vue";
//courses:[] ,//课程数据

export default reactive({
  data: [
    {"id":1, "name": "python"},
    {"id":2, "name": "java"},
  ]
});

export const add_course = ()=>{
  //添加课程
  console.log("添加课程");
}
export const get_course=(id)=>{
  //获取课程信息
}
export const del_course =()=>{
  //删除课程
}

 

src/api/students.js,代码:

import {reactive} from "vue";
//students:[] ,//学生数据
export default reactive({
  data: [
    {"id":1,"name":"小明","age":17},
    {"id":2,"name":"小明","age":17},
  ]
});


export const add_student = ()=>{
  //添加学生
  console.log("添加学生");

}

export const get_student =()=>{
  //获取学生
}

export const del_student =()=>{

}

src/App.vue,代码:

<script setup>
import List from "./views/List.vue"
import Register from "./views/Register.vue";
import Goods from "./views/Goods.vue";
import Group from "./views/Group.vue";
// 使用js提供的location对象,获取url地址的路径
// script声明的所有变量都会被自动填充到data中,可以直接在template模板标签中使用
let url = location.pathname;
</script>

<template>
<!--  <List v-if="url==='/list'"></List>-->
<!--  <Register v-if="url==='/reg'"></Register>-->
<!--  <Goods></Goods>-->
<Group></Group>
</template>

<style scoped>
</style>

 

语法代码

8.2.1 基本语法

 src/GroupApi.vue

<script setup>
import {ref,reactive,watch,onMounted,computed} from "vue";

/**
 * 声明只读变量
 */
let num1 = 10; // 声明一个只读变量,无法在template中进行双向数据绑定

/**
 * 声明响应式变量
 * ref函数的作用就是用于声明vue的基本数据类型[Number,String,Boolean/undefined/Array等]的响应式变量,可以进行双向数据绑定
 * reactive 函数的作用就是用于声明vue的复杂数据类型[Object]的响应式变量,可以进行双向数据绑定
 */
let num2 = ref(100);
let data = ref([
  {"id":1, "name": "小明", "age": 11},
  {"id":2, "name": "小白", "age": 18},
  {"id":3, "name": "小华", "age": 17},
  {"id":4, "name": "小绿", "age": 18},
]);
let student_info = reactive({
  "id": 1,
  "name": "小白",
  "age": 16
})
/**
 * 修改变量的操作
 */
const change_data1 = ()=>{
  // 修改ref响应式变量的值,需要通过value来改动
  num2.value  = 30000;
  console.log(num2);
}

const change_data2 = ()=>{
  // 修改reactive响应式变量的值,不能修改变量本身,可以修改变量内部的属性,直接赋值即可。
  student_info.age = 20
}
// 监听属性写法
watch(
    ()=>num2.value, // 监听ref响应式变量,参数1是一个函数,返回值是被监听的ref变量的value属性
    ()=>{
      // 值发生改变时自动调用的代码
      console.log("num2改变了",num2)
    }
)

watch(
    student_info,  // 监听reactive响应式变量,参数1就是被监听的reactive变量
    ()=>{
      console.log("student_info改变了",student_info);
    }
)

/**
 * 钩子方法
 */
// created 钩子,vue初始化完成时自动自动的。但是在组合API中时没有created钩子的
// 原因开发者在 <script setup>标签中缩写的所有所有代码,默认都是在created钩子中执行的。
console.log("created执行了,此时vue刚完成初始化,还是渲染template")

// mounted钩子方法,在组合API中叫onMounted
onMounted(()=> {
  // 视图被渲染以后,执行代码。
  console.log("Mounted执行了,此时vue已经渲染了html内容");
})
/**
 * computed 计算属性
 */
let data1 = ref(10);
let data2 = ref(20);

let result = computed(()=>{
  return data1.value+data2.value;
})

</script>

<template>
  <h2>变量声明</h2>
  <p>num1={{num1}}</p>
  <input type="text" v-model="num1">
  <hr>
  <p>num2={{num2}}</p>
  <input type="text" v-model="num2">
  <ul>
    <li v-for="item in data">{{item}}</li>
  </ul>
  {{student_info}}}<br>
  {{student_info.name}}<br>
  <hr>
  <h2>修改变量</h2>
  <button @click="change_data1">修改ref数据</button>
  <button @click="change_data2">修改reactive数据</button>

  <hr>
  <h2>计算属性</h2>
  <input type="text" size="1" v-model.number="data1"> + <input type="text" v-model.number="data2"> = {{result}}

</template>

<style scoped>

</style>

 

src/App.vue,代码:

<script setup>
import List from "./views/List.vue"
import Register from "./views/Register.vue";
import Goods from "./views/Goods.vue";
import Group from "./views/Group.vue";
import GroupApi from "./GroupApi.vue";
// 使用js提供的location对象,获取url地址的路径
// script声明的所有变量都会被自动填充到data中,可以直接在template模板标签中使用
let url = location.pathname;
</script>

<template>
<!--  <List v-if="url==='/list'"></List>-->
<!--  <Register v-if="url==='/reg'"></Register>-->
<!--  <Goods></Goods>-->
<!--<Group></Group>-->
  <GroupApi></GroupApi>
</template>

<style scoped>
</style>

 

8.2.2 参数传递

父传子

在父组件中,传递数据需要通过组件标签名的属性进行传递,而子组件中,通过defineProps接受父组件传递过来的数据。

src/views/User.vue,代码:

 

<script setup>
import Info from "./Info.vue";
import {ref} from "vue";
let str_data = ref("hello world")
</script>

<template>
  <h1>User组件</h1>
  <input type="text" v-model="str_data">
  <Info :str_message="str_data"></Info>
</template>

<style scoped>

</style>

src/views/Info.vue,代码:

<script setup>
// import {defineProps} from "vue";
// 使用defineProps来接收父组件的数据
const props = defineProps(["str_message"])
</script>

<template>
  <h1>Info子组件</h1>
  <p>子组件中接受来自父组件的数据</p>
  <p>{{props.str_message}}</p>
</template>

<style scoped>

</style>

src/App.vue,代码:

<script setup>
import List from "./views/List.vue"
import Register from "./views/Register.vue";
import Goods from "./views/Goods.vue";
import Group from "./views/Group.vue";
import GroupApi from "./GroupApi.vue";
import User from "./views/User.vue";
// 使用js提供的location对象,获取url地址的路径
// script声明的所有变量都会被自动填充到data中,可以直接在template模板标签中使用
let url = location.pathname;
</script>

<template>
<!--  <List v-if="url==='/list'"></List>-->
<!--  <Register v-if="url==='/reg'"></Register>-->
<!--  <Goods></Goods>-->
<!--<Group></Group>-->
<!--  <GroupApi></GroupApi>-->
  <User></User>
</template>

<style scoped>
</style>

 

 src/views/Info.vue,代码:

<script setup>
// import {defineProps} from "vue";
// 使用defineProps来接收父组件的数据
const props = defineProps({
  str_message:Number,
})
</script>

<template>
  <h1>Info子组件</h1>
  <p>子组件中接受来自父组件的数据</p>
  <p>{{props.str_message}}</p>
</template>

<style scoped>

</style>

 

  

src/views/User.vue,代码:

<script setup>
import Info from "./Info.vue";
import {ref} from "vue";
let str_data = ref("hello world");
let num_data = ref(10);
</script>

<template>
  <h1>User组件</h1>
  <input type="text" v-model="str_data">
  <input type="text" v-model="num_data">
  <Info :str_message="str_data" :num_message="num_data"></Info>
</template>

<style scoped>

</style>

 

src/views/Info.vue,代码:

<script setup>
// import {defineProps} from "vue";
// 使用defineProps来接收父组件的数据
const props = defineProps({
  str_message: {
    type: String,
    default:"没有数据",
  },
  num_message:{
    type:Number,
    default:0,
  },
})
</script>

<template>
  <h1>Info子组件</h1> 
  <p>子组件中接受来自父组件的数据</p>
  <p>{{props.str_message}}</p>
  <p>{{props.num_message}}</p>
</template>

<style scoped>

</style>

 

 

src/views/User.vue,代码:

 

<script setup>
import Info from "./Info.vue";
import {ref,reactive} from "vue";
let str_data = ref("hello world");
let num_data = ref(10);
let obj_data = reactive({
  id:1,
  name: "小明",
  age:18,
});
</script>

<template>
  <h1>User组件</h1>
  <input type="text" v-model="str_data">
  <input type="text" v-model="num_data">
  <Info
      :str_message="str_data"
      :num_message="num_data"
      :obj_data="obj_data"
  ></Info>
</template>

<style scoped>

</style>

 

src/views/Info.vue,代码:

<script setup>
// import {defineProps} from "vue";
// 使用defineProps来接收父组件的数据
import {ref,watch} from "vue";
const props = defineProps({
  str_message: {
    type: String,
    default:"没有数据",
  },
  num_message:{
    type:Number,
    default:0,
  },
  obj_data:Object,
})

let num = ref(10)
watch(
    num,
    ()=>{
      console.log(num.value)
    }
)

</script>

<template>
  <h1>Info子组件</h1>
  <p>子组件中接受来自父组件的数据</p>
  <p>{{props.str_message}}</p>
  <p>{{props.num_message}}</p>
  <input type="text" v-model="num">
  <p>obj_data={{props.obj_data}}</p>
</template>

<style scoped>

</style>

 

子传父

在子组件中通过defineEmits先声明要注册的事件源,然后通过defineEmits的返回值emits进行调用事件源进行参数传递,在父组件中,直接声明方法绑定到子组件标签名中即可。

src/views/Info.vue,代码:

 

<script setup>
// import {defineProps} from "vue";
// 使用defineProps来接收父组件的数据
import {ref,watch} from "vue";
//定义事件
//注册的事件源
const emits = defineEmits(["num_change"])
// 使用defineProps来接收父组件的数据
const props = defineProps({
  str_message: {
    type: String,
    default:"没有数据",
  },
  num_message:{
    type:Number,
    default:0,
  },
  obj_data:Object,
})

let num = ref(10)
watch(
    num,
    ()=>{
      console.log(num.value);
      emits("num_change",num);
    }
)

</script>

<template>
  <h1>Info子组件</h1>
  <p>子组件中接受来自父组件的数据</p>
  <p>{{props.str_message}}</p>
  <p>{{props.num_message}}</p>
  num=<input type="text" v-model="num">
  <p>obj_data={{props.obj_data}}</p>
</template>

<style scoped>

</style>

 

src/views/User.vue,代码:

<script setup>
import Info from "./Info.vue";
import {ref,reactive} from "vue";
let str_data = ref("hello world");
let num_data = ref(10);
let obj_data = reactive({
  id:1,
  name: "小明",
  age:18,
});

const get_num = (data)=>{
   console.log("父组件中接收数据data=", data.value);
}

</script>

<template>
  <h1>User组件</h1>
  <input type="text" v-model="str_data">
  <input type="text" v-model="num_data">
  <Info
      :str_message="str_data"
      :num_message="num_data"
      :obj_data="obj_data"
      @num_change="get_num"
  ></Info>
</template>

<style scoped>

</style>

 

 

 

 

 ref引用template标签对象[抓取标签对象]

 src/views/Info.vue,代码:

<script setup>
// import {defineProps} from "vue";
// 使用defineProps来接收父组件的数据
import {ref,watch} from "vue";
//定义事件
//注册的事件源
const emits = defineEmits(["num_change"])
// 使用defineProps来接收父组件的数据
const props = defineProps({
  str_message: {
    type: String,
    default:"没有数据",
  },
  num_message:{
    type:Number,
    default:0,
  },
  obj_data:Object,
})

let num = ref(10)
watch(
    num,
    ()=>{
      console.log(num.value);
      emits("num_change",num);
    }
)

/**
 * ref引用template标签对象[抓取标签对象]
 */

let p1 = ref(null);  // 这里的p1就是<p ref="p1">
const get_ele= ()=>{
  console.log(p1);  // 这里的p1就是<p ref="p1">
  console.log(p1.value); // 这里得到的就是原生的js的标签对象
}

</script>

<template>
  <h1>Info子组件</h1>
  <p>子组件中接受来自父组件的数据</p>
  <p>{{props.str_message}}</p>
  <p>{{props.num_message}}</p>
  num=<input type="text" v-model="num">
  <p ref="p1" @click="get_ele">obj_data={{props.obj_data}}</p>
</template>

<style scoped>

</style>

 

posted @ 2025-03-14 02:25  minger_lcm  阅读(43)  评论(0)    收藏  举报