Welcome to my b|

Khru

园龄:2年11个月粉丝:22关注:1

2024-11-27 22:53阅读: 22评论: 0推荐: 0

Vue-组合式API

vite构建工具

搭建vue3项目

  • npm create vite
  • cd dir-vite : 进入项目目录
  • npm install: 安装依赖
  • npm run dev: 启动项目
Local: http://localhost:5173/
Network: use --host to expose
Vue DevTools: Open http://localhost:5173/__devtools__/ as a separate window
Vue DevTools: Press Alt+Shift+D in App to toggle the Vue DevTools

启动过程

  1. 启动服务
    当执行npm run dev时, 使用了vite工具启动了一个调试服务器(dev Server). 监听5173端口.
    1. 会将vite-vue作为网站的根目录
    2. 会将index.html作为网站的默认文件
    3. 当浏览器访问localhost:5173时, 调试服务器会将index.html返回给浏览器
  2. 加载main.js
    1. index.html中, 加载了main.js
    2. main.js导入App组件

单文件组件

一个.vue文件就是一个单文件组件, 包括

  • template: 模板, 用于编写HTML
  • script: 逻辑, 用于编写JS
  • style: 样式, 用于编写CSS
<template>
<!-- 组件的模板部分 -->
计数器:{{ count }}
<button @click="handleClick">点击+1</button>
</template>
<script setup>
import { ref } from 'vue'
const count = ref(0)
function handleClick() {
count.value++
}
</script>
<style>
/* 组件的样式 */
</style>

组合式API

setup语法糖

vue项目中, 通常使用setup语法简化书写

  1. 在setup语法中定义变量, 可以直接在模板中使用
  2. 在setup语法中定义函数, 可以直接在模板中使用
  3. 导入的组件对象, 可以直接在模板中使用

常用的组合式API

  • ref
  • computed
  • watch
  • onMounted

ref

响应性 API,用于创建一个响应式的数据源ref对象, ref 对象具有一个指向内部值的 .value 属性。

import { ref } from 'vue'
// 声明变量
const count = ref(0);
// 使用变量, 需要通过.value属性来访问
console.log(count.value); // 输出 0
// 在 setup 函数中返回 ref
export default {
setup() {
const count = ref(0);
return { count };
}
};
<template>
<button @click="handleClick">显示/隐藏</button>
<div v-show="flag">这是一个div</div>
</template>
<script setup>
import { ref } from 'vue'
// 声明变量
const flag = ref(true)
// 声明函数
function handleClick() {
flag.value = !flag.value
}
</script>

computed

<template>
姓: <input type="text" v-model="firstname" /> <br />
名: <input type="text" v-model="lastname" /> <br />
全名: {{ fullname }}
</template>
<script setup>
import { computed, ref } from 'vue'
const firstname = ref('')
const lastname = ref('')
const fullname = computed(() => {
return firstname.value + lastname.value
})
</script>

创建可读写的计算属性:

const doubleCount = computed({
get: () => {
return count.value * 2;
},
set: (newValue) => {
count.value = newValue / 2;
}
});

watch

<template>
单价: 5 <br />
数量: <input type="text" v-model.number="num" /> <br />
总价: {{ total }}
</template>
<script setup>
import { ref, watch } from 'vue'
const num = ref(0)
const total = ref(0)
watch(num, () => {
total.value = num.value * 5
})
</script>

onMounted

生命周期钩子函数,用于在组件挂载(即元素被插入到 DOM 中)之后执行代码。这是执行副作用操作(如设置定时器、发起网络请求、直接操作 DOM 等)的理想时机。

<template>
<ul>
<li v-for="book in books" :key="book.id">{{ book.name }}</li>
</ul>
</template>
<script setup>
import { onMounted, ref } from 'vue'
const books = ref([])
onMounted(() => {
// 在onMounted中给books赋值
setTimeout(() => {
books.value = [
{ id: 1, name: 'vue' },
{ id: 2, name: 'gis' },
{ id: 3, name: 'js' },
]
}, 1000)
})
</script>

组件

简单使用

  1. 定义组件

components目录下, 创建组件文件TheCounter.vue

<template>
计数器:{{ count }}
<button @click="handleClick">点击+1</button>
</template>
<script setup>
import { ref } from 'vue'
const count = ref(0)
console.log(count)
function handleClick() {
count.value++
}
</script>
<style>
/* 组件的样式 */
</style>
  1. 导入组件

App.vue中, 通过import语法导入组件对象

<script setup>
// 2. 导入组件对象
import TheCounter from './components/TheCounter.vue'
</script>
  1. 引用组件

App.vue的模板中, 通过组件名引用组件

<template>
<!-- 3. 引用组件 -->
<TheCounter></TheCounter>
</template>

父传子

父组件向子组件传递数据

  1. 在父组件中, 借助自定义属性
  2. 在子组件中, 通过defineProps接受

defineProps

  1. 只能在 <script setup> 的顶层使用
  2. type: StringNumberBooleanArrayObjectDate
  3. default : 默认值
  4. required: true,指定一个属性是必需的
  5. validator,用于自定义验证函数

静态绑定

<template>
<TheBlog title="01-vue"></TheBlog>
<TheBlog title="02-gis"></TheBlog>
<TheBlog title="03-js"></TheBlog>
</template>
<script setup>
import TheBlog from './components/TheBlog.vue'
</script>
<template>
<div>{{ title }}</div>
</template>
<script setup>
const props = defineProps({
title: {
type: String,
required: true,
},
})
</script>

动态绑定

<template>
<TheBlog title="01-vue"></TheBlog>
<TheBlog title="02-gis"></TheBlog>
<!-- 将属性值和App组件中的一个状态动态绑定 -->
<TheBlog :title="t"></TheBlog>
</template>
<script setup>
import TheBlog from './components/TheBlog.vue'
import { ref } from 'vue'
const t = ref('03-标题')
</script>

子传父

子组件向父组件传递数据

  1. 在子组件中, 触发自定义事件
  2. 在父组件中, 监听自定义事件, 在回调函数中通过参数获取

自定义事件

const emit = defineEmits(['eventName1', 'eventName2']);

<script setup>
const emit = defineEmits({
eventName1: null, // 不进行类型检查
eventName2: (payload) => {
// 类型检查函数
if (typeof payload !== 'string') {
console.warn('eventName2 expects a string as the payload');
}
}
});
</script>
<template>
<button @click="updateValue(newvalue)">更新值</button>
</template>
<script setup>
import { ref } from 'vue';
const newvalue = ref('新值')
const emit = defineEmits(['childclick']);
function updateValue(newValue) {
emit('childclick', newValue);
}
</script>
<template>
<ChildComponent @childclick="handleChildClick($event)" />
<p>当前值: {{ modelValue }}</p>
</template>
<script setup>
import { ref } from 'vue';
import ChildComponent from './components/test.vue';
const modelValue = ref('初始值');
function handleChildClick(value) {
modelValue.value = value
}
</script>

实例: 根据id关闭指定组件

<template>
<div>
{{ title }}
<button @click="handleClick">关闭</button>
</div>
</template>
<script setup>
const props = defineProps({
title: {
type: String,
required: true,
},
id: {
type: Number,
required: true,
},
})
const emits = defineEmits(['close'])
function handleClick() {
emits('close', props.id)
}
</script>
<template>
<!-- v-if和v-for不能应用于同一个元素 -->
<TheBlog
v-for="blog in showBlogs"
:key="blog.id"
:title="blog.title"
:id="blog.id"
@close="handleClose"
></TheBlog>
</template>
<script setup>
import TheBlog from './components/test.vue'
import { ref, computed } from 'vue'
const blogs = ref([
{ id: 1, title: '01-vue', isShow: true },
{ id: 2, title: '02-gis', isShow: true },
{ id: 3, title: '03-mapbox', isShow: true },
])
const showBlogs = computed(() => {
return blogs.value.filter((item) => item.isShow)
})
function handleClose(id) {
console.log(id)
const blog = blogs.value.find((item) => item.id == id)
blog.isShow = false
}
</script>

provide和inject

  • provide: 提供. 数据由祖先组件提供
  • inject: 注入. 由后代组件获取数据

app应用实例上挂载

const app = createApp(App)
// 通过app定义全局的对象: $map
app.provide('$map', { map: 'world' })

app对应的子组件中, 可以直接引用

import { inject } from 'vue'
const map = inject('$map')
console.log(map)

插槽

  1. 在组件中预留一个slot插槽
  2. 在组件渲染时, 将内容插入slot

普通插槽

在子组件定时时, 预留插槽

<template>
<!-- 预留一个slot插槽 -->
<slot></slot>
</template>

在渲染子组件时, 会使用组件内部的内容替换掉slot部分

<TheComputer>
<div>
<h3>名称: MacBookPro</h3>
<p>型号: MBP 14 M1</p>
</div>
</TheComputer>

具名插槽

在定义slot插槽时, 设置name属性

<template>
<!-- 具名插槽 -->
<slot name="cpu"></slot>
<slot name="memery"></slot>
</template>

在渲染时, 通过v-slot指令指定插槽的名称

<template>
<TheComputer>
<template v-slot:cpu>
<!-- 这里的内容插入到名字叫cpu的插槽中 -->
CPU: M1 Pro
</template>
<template #memery> Memery: 16G </template>
</TheComputer>
</template>

作用域插槽

将子组件的属性及其值传递给父组件,以便在父组件的插槽内容中使用

  1. 默认插槽
<template>
<div>
<slot :userprop="user"></slot>
</div>
</template>
<script setup>
const user = reactive({
name: '张三',
age: 30})
</script>
<template>
<test>
<template v-slot:default="slotProps">
{{ slotProps.userprop.name }} - {{ slotProps.userprop.age }}
</template>
</test>
</template>
  1. 具名插槽
<template>
<div>
<slot name="body" msg="这是消息" :age="12"></slot>
</div>
</template>
<template>
<test>
<template #body="data">
这是插槽内部传递的数据: {{ data.msg }} age: {{ data.age }}
</template>
</test>
</template>

本文作者:Khru

本文链接:https://www.cnblogs.com/khrushchefox/p/18573277

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   Khru  阅读(22)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起