Vue系统学习day01
Vue01
创建项目:(这一指令将会安装并执行 create-vue,)
npm create vue@latest
:Vue 官方的项目脚手架工具
项目结构介绍:
setup组合式编程
export default
命令用于指定模块的默认输出,因此在一个模块中,export default命令只能使用一次
1、setup选项的执行时机在Vue的beforeCreate生命周期之前
<script>
export default{
setup(){
console.log('setup')
},
beforeCreate(){
console.log('beforeCreate')
}
}
</script>
2、setup写代码的特点是
可以在这里面定义数据+函数==》但是所定义的必须以对象形式return进行返回
<!-- 复杂写法 -->
<script>
export default{
setup(){
const msg='hello world'
const logMessage=()=>{
console.log('msg')
}
return {
msg,
logMessage
}
}
}
</script>
3、<script setup>:让组合式API语法更简单
<script setup>
//数据
const msg='hello world'
//函数
const logMessage=()=>{
console.log('msg')
}
</script>
4、不再有this的调用
reactive和ref函数
1、通过这两个函数的调用都可以生成
响应式数据
2、reactive函数不能处理简单类型的数据(可以通过响应式对象去调用对象的属性)
ref函数可以处理简单类型和对象类型的数据
3、ref使用更为简单,但是对应的ref内部调用实现必须通过.value访问修改
注意这个.value只是在script中调用的时候需要通过此进行调用
4、ref函数相较于来说更为简单适用
使用流程:reactive({对象})
<script setup>
//导入函数
import { reactive } from 'vue';
//对象类型的参数通过reactive函数封装成响应式数据对象
// 执行函数,传入一个对象格式的参数 ---》返回值是一个响应式数据对象
const state =reactive({
count: 0
})
// 函数
const setCount =()=>{
state.count++
}
</script>
<template>
<div>
<button @click="setCount">{{ state.count }}</button>
</div>
</template>
ref(基础类型)或者ref({对象类型})
<script>
//导入函数
import { ref } from 'vue';
//对象类型或者对象类型的数据都可以作为一个参数给ref函数返回一个响应式数据对象
// 执行函数,传入一个普通参数类型或者对象格式的参数 ---》返回值是一个响应式数据对象
const count = ref(0);
const setCount =()=>{
//修改ref函数产生的响应式数据对象的值,必须通过.value的形式修改
count.value++
}
</script>
<template>
<div>
<button @click="setCount">{{ count }}</button>
</div>
</template>
cemputed计算属性函数
1、计算属性的函数只用来计算,不要有多余的操作
2、一般计算属性的值为只读的
<script setup>
// 导入函数
import {ref,computed} from 'vue'
//创建一个原始的响应的数组--》通过ref函数转换为一个响应式的数组
const list =ref([1,2,3,4,5,6,7,8,9,10])
//执行函数,通过computed函数,return 计算得到的数组
const computedList = computed(()=>{
// 根据计算得到一个新的数据
// 通过.value去获取响应式数据
return list.value.filter(item=>item>2)
})
//设置一个定时器(setTimeout函数只执行一次)
setTimeout(()=>{
// push函数添加一个元素
list.value.push(11)
},2000)
</script>
<template>
<div>
原始数组{{ list }}
</div>
<div>
计算之后的数组:{{ computedList }}
</div>
</template>
watch侦听函数(其中如果需要监听一个对象的属性的话需要通过精确监听进行实现)
1、侦听单个参数其中在对于watch函数侦听的参数而言,不需要通过.value获取对应的值,watch会自动进行获取
<script setup>
import { ref, watch } from 'vue';
// 导入函数
const count = ref(0)
// 定义一个函数
const setCount=()=>{
count.value++
}
//通过watch函数监听一个参数 count的变化
// 语法:watch(监听的变量,回调函数)
watch(count,(newValue,oldValue)=>{
console.log('newValue',newValue)
console.log('oldValue',oldValue)
})
</script>
<template>
<div>
<button @click="setCount">{{ count }}</button>
</div>
</template>
2、侦听多个参数
<script setup>
import { ref, watch } from 'vue';
// 定义两个参数
const count = ref(0)
const name = ref('张三')
// 定义一个函数
const setCount=()=>{
count.value++
}
const setName=()=>{
name.value='李四'
}
//使用watch函数监听多个参数的变化
//语法:watch([监听的变量,监听的变量],回调函数)
watch([count,name],
([newValue1,newValue2],[oldValue1,oldValue2])=>{
console.log('newValue1',newValue1)
console.log('newValue2',newValue2)
console.log('oldValue1',oldValue1)
console.log('oldValue2',oldValue2)
}
)
</script>
<template>
<div>
<button @click="setCount">改变数值:{{ count }}</button>
<button @click="setName">改变名字:{{ name }}</button>
</div>
</template>
3、侦听参数立即执行
<script setup>
import { ref,watch } from 'vue';
const count = ref(0)
// 定义一个函数
const setCount=()=>{
count.value++
}
// 通过watch函数监听一个参数 count的变化同时立即执行回调函数
// 语法:watch(监听的变量,回调函数,{immediate:true})
watch(count,(newValue,oldValue)=>{
console.log('newValue',newValue)
console.log('oldValue',oldValue)
},{immediate:true})
</script>
<template>
<div>
<button @click="setCount">count的变化{{ count }}</button>
</div>
</template>
watch函数的精确侦听(一般不建议使用deep进行深度监听,太消耗性能了)
<script setup>
import { ref, watch } from 'vue';
// 定义一个对象类型的变量:
const student=ref({
name:'张三',
age:18,
gender:'男'
})
// 定义一个函数
const setName=()=>{
student.value.name='李四'
}
const setAge=()=>{
student.value.age=20
}
// 通过watch函数进行精确的监听
// 语法:watch(()=>监听的对象.对象的属性,回调函数)
watch(()=>student.value.name,
(newValue,oldValue)=>{
console.log('newValue',newValue)
console.log('oldValue',oldValue)
}
)
watch(()=>student.value.age,
(newValue,oldValue)=>{
console.log('newValue',newValue)
console.log('oldValue',oldValue)
}
)
</script>
<template>
<div>
<button @click="setName">将名字改为{{ student.name }}</button>
<button @click="setAge">将年龄改为{{ student.age }}</button>
</div>
</template>
watch函数的深度侦听
<script setup>
import { ref, watch } from 'vue';
// 定义一个对象类型的变量:
const student=ref({
name:'张三',
age:18,
gender:'男'
})
// 定义一个函数
const setName=()=>{
student.value.name='李四'
}
const setAge=()=>{
student.value.age=20
}
// 通过watch函数进行深层次的监听 deep:true(这样的深层侦听是十分的消耗性能的所以一般不建议使用)
// 语法:watch(监听的变量,回调函数,{deep:true})
watch(student,
(newValue,oldValue)=>{
console.log('newValue',newValue)
console.log('oldValue',oldValue)
},
{deep:true}
)
</script>
<template>
<div>
<button @click="setName">将名字改为{{ student.name }}</button>
<button @click="setAge">将年龄改为{{ student.age }}</button>
</div>
</template>
组合式API编程中生命周期函数可以多次调用
模版引用:(模版引用必须在挂载完毕了之后才能获取到对应的DOM元素或者组件实例对象)
通过ref标识获取对应的DOM对象或者是组件的实例对象
App.vue:
<script setup>
// 模版引用
import TestCom from './test-com.vue';
// 导入ref函数
import { ref, onMounted } from 'vue';
//调用ref函数得到ref对象
const h1Ref = ref(null);
const comRef = ref(null);
// 组件挂载完毕到页面上才能获取ref对象
onMounted(() => {
// 打印ref对象
console.log(h1Ref.value);
console.log(comRef.value);
})
</script>
<template>
<div>
<!-- 通过ref属性获取dom元素(获取的为整个标签元素) -->
<h1 ref="h1Ref">hello</h1>
<!-- 通过ref属性获取子组件元素(返回的为组件实例) -->
<TestCom ref="comRef"></TestCom>
</div>
</template>
test-com.vue:
<script setup>
import { ref } from 'vue';
const name = ref('张三')
const setName =()=>{
name.value = '李四'
}
// 通过defineExpose暴露给父组件使用
defineExpose({
name,
setName
})
</script>
<template>
<div>test组件</div>
</template>
跨层组件通信(provide传递和inject接收)
**provide(key,value)
—》**这个value可以是普通数据,响应式数据,方法
const 变量=inject(key)
顶层组件
<script setup>
// 引入底层组件
import { provide, ref } from 'vue';
import DownCom from './05_provide-inject.vue'
// 1、通过provide提供普通数据
provide('msg', '我是顶层组件')
// 2、通过provide提供响应式数据
const count =ref(0)
provide('count', count)
// 通过一个定时器修改响应式数据:2s后响应式数据变为100
setTimeout(()=>{
count.value = 100
},2000)
// 3、通过provide提供方法(谁的数据谁负责)
const addCount = () => {
count.value++
}
provide('addCount', addCount)
</script>
<template>
<div>
<h2>顶层组件</h2>
<DownCom/>
</div>
</template>
底层组件
<script setup>
import { inject } from 'vue';
// 1、接收普通数据从顶层组件
const msgData = inject('msg')
// 2、接收响应式数据从顶层组件
const countData = inject('count')
// 3、接收方法从顶层组件
const addCount = inject('addCount')
</script>
<template>
<div>
<h3>底层组件</h3>
<p>接收到顶层组件的普通数据:{{msgData}}</p>
<p>接收到顶层组件的响应式数据:{{countData}}</p>
<button @click="addCount">通过addCount方法修改响应式数据</button>
</div>
</template>
综合案例:
App.vue:
<script setup>
import axios from 'axios';
import Edit from './components/Edit.vue'
import { ref,onMounted } from 'vue'
// TODO: 列表渲染
// 声明响应式数据list
const list = ref([]);
// 调用接口获取数据(以同步的形式执行异步的调用)
const getList = async ()=>{
// 调用接口
const res = await axios.get('/list')
// 赋值给list
list.value = res.data
}
// 页面加载时调用接口
onMounted(() => getList())
// TODO: 删除功能
const del=async(id)=>{
// console.log(id);
// 此处是是通过一个 模版字符串进行拼接字符串`用户名:${username}`
await axios.delete(`/del/${id}`)
getList()
}
// 将Edit组件对象引入进来
const editRef = ref(null);
// TODO: 编辑功能(1、打开编辑框)-2、回填数据-3、更新数据
const edit=async(row)=>{
// 打开编辑框
editRef.value.open(row)
}
</script>
<template>
<div class="app">
<el-table :data="list">
<el-table-column label="ID" prop="id"></el-table-column>
<el-table-column label="姓名" prop="name" width="150"></el-table-column>
<el-table-column label="籍贯" prop="place"></el-table-column>
<el-table-column label="操作" width="150">
<template #default="{row}">
<el-button type="primary" @click="edit(row)" link>编辑</el-button>
<el-button type="danger" @click="del(row.id)" link>删除</el-button>
</template>
</el-table-column>
</el-table>
</div>
<Edit ref="editRef" @on-update="getList"/>
</template>
<style scoped>
.app {
width: 980px;
margin: 100px auto 0;
}
</style>
Edit.vue:
<script setup>
// TODO: 编辑
import { ref } from 'vue'
import axios from 'axios'
// 弹框开关
const dialogVisible = ref(false)
// 定义响应式数据
const form =ref({
name:'',
place:'',
id:''
})
// 封装一个方法用于打开弹框
const open = (row) => {
dialogVisible.value = true
// 回填数据
form.value.name = row.name
form.value.place = row.place
form.value.id = row.id
}
// 将open方法暴露出去
defineExpose({
open
})
// 子组件向通知父组件更新数据
const emit = defineEmits(['on-update'])
// 更新数据
const onUpdated=async() => {
await axios.patch(`/edit/${form.value.id}`, {
name: form.value.name,
place: form.value.place,
})
//关闭弹窗
dialogVisible.value = false
//通知父组件进行更新
emit('on-update')
}
</script>
<template>
<el-dialog v-model="dialogVisible" title="编辑" width="400px">
<el-form label-width="50px">
<el-form-item label="姓名">
<el-input placeholder="请输入姓名" v-model="form.name"/>
</el-form-item>
<el-form-item label="籍贯">
<el-input placeholder="请输入籍贯" v-model="form.place"/>
</el-form-item>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click="dialogVisible = false">取消</el-button>
<el-button type="primary" @click="onUpdated">确认</el-button>
</span>
</template>
</el-dialog>
</template>
<style scoped>
.el-input {
width: 290px;
}
</style>
实现效果
查询所有列表信息
删除列表元素
编辑更新列表元素