echarts自适应大小
myChart.setOption(option)
window.onresize = function () {
myChart.resize()
}
setup在create之前,所有变量方法都要return。
function btn() {}
或者
const btn = () =>{}
二、组合式API(常用)
1.import { ref } from 'vue
当ref的值发生改变时,视图层会自动更新。
const name = ref('班海斌')
function btn() {
name.value = '韦艳迎'
}
2. import { reactive } from 'vue
-
为值创建响应式引用
-
定义基本普通数据类型不能用reactive,用ref
-
reactive主要定义复杂数据类型,如数组、对象
-
可相应深层次的数据,如多维数组
-
reactive返回一个响应式的proxy对象
function btn() {
name = '韦艳迎'
}
3. import { toRef } from 'vue
响应式数据
ref的本质是复制粘贴一份数据,脱离了与原数据的交互
ref函数将对象中的属性变成响应式数据,修改响应式数据是不会影响到原数据,但是会更新视图层
toRef的本质是引用,与原数据有交互,修改响应式数据会影响到原数据,但不会更新视图层
toRef接受两个参数(要操作的对象、对象的某个属性)
4. import { toRefs } from 'vue
用于批量设置多个数据为响应式数据
toRefs与原数据有交互,修改响应式数据会影响到原数据,但不会更新视图层
toRefs还可以与其他响应式数据交互,更加方便处理视图数据
<h1> {{ name }} </h1>
<h1> {{ age }} </h1>
setup() {
const obj = { name: '班海斌', age: 18, sex: '男'}
const newObject = reactive(obj)
return { ...torefs(newObject) }
}
5.computed,监听数据变化; import { computed } from 'vue
<input type='number' v-model="age1"/>
<input type='number' v-model="age2"/>
总和:<input type='number' v-model="sum"/>
setup() {
const age1 = ‘ ’
const age2 = ' '
const res = reactive( { age1, age2 })
const sum = computed( () =>{
return age1 + age2
})
return { ...torefs(res), sum }
}
6.watch,监听数据变化; import { watch } from 'vue
setup() {
const num1 = ref(0)
const num3 = reactive( {
name : '班海斌',
age: { num: 1}
})
// 监听一个
watch( num1, ( newVal, oldVal ) = > {
console.log( newVal, oldVal )
})
// 监听多个
watch( [num1, num2], ( newVal, oldVal ) = > {
console.log( newVal, oldVal )
})
// 监听整个reactive响应数据变化,只能监听到最新的结果newVal=oldVal
watch( num3, ( newVal, oldVal ) = > {
console.log( newVal, oldVal )
})
// 监听reactive响应数据中某一个值的变化
watch( () => num3.age.num, ( newVal, oldVal ) = > {
console.log( newVal, oldVal )
}, { immediate: true } ) // { immediate: true } ,进入页面立即开启监听
return { num1,num3}
}
7.watchEffect,监听数据变化; import { watchEffect } from 'vue
watchEffect如果存在的话,在组件初始化的时候就会执行一次收集依赖
watchEffect拿不到新值和旧值
watchEffect不需要指定监听的属性,他会自动收集依赖,只要我们回调中引用到了响应式的属性
那么当这些属性变更的时候,这个回调都会执行,而watch只能监听指定的属性而做出变更。
setup() {
const p1= ref(0)
const res = watchEffect( () => {
const a = p1.value
})
res() // 停止数据监听
}
8.shallowRef和shallowReactive
shallowRef只处理基本类型数据
shallowReactive只处理第一层数据,对象第一层数据
const p1 = shallowReactive({
name: '班海斌',
age: {
num: 0
}
})
三、组件传值
1.普通页面传值
父:
setup() {
const p1 = reactive( { name: '班海斌',age: 18})
provide( 'name', p1) // 传值
return { p1 }
}
子:
setup() {
const p1 = inject( ‘name') //接收传值
return { p1 }
}
2.点击给子组件传值
<button @click="btn">点击传值给父组件</button》
<helloWord ref="tableRef"/>
父组件:
setup() {
const tableRef = ref()
const p1 = reactive( { name: '班海斌',age: 18})
function btn () {
tableRef.value.myChild( p1 )
}
return{ tableRef, p1, btn }
}
子组件:
setup() {
function myChild(val) {}
return { myChild }
}
getCurrentInstance()
1、概述:一个很重要的方法,获取当前组件的实例、上下文来操作router和vuex等。
2、使用:由vue提供,按需引入:import { getCurrentInstance} from 'vue';
import { getCurrentInstance } from 'vue';
// 获取当前组件实例
const instance = getCurrentInstance();
// 获取当前组件的上下文,下面两种方式都能获取到组件的上下文。
const { ctx } = getCurrentInstance(); // 方式一,这种方式只能在开发环境下使用,生产环境下的ctx将访问不到
const { proxy } = getCurrentInstance(); // 方式二,此方法在开发环境以及生产环境下都能放到组件上下文对象(推荐)
// ctx 中包含了组件中由ref和reactive创建的响应式数据对象,以及以下对象及方法;
例如:
ctx.$notify.success({ title: '成功', message: '导出成功' })
props(为组件的props),context(包含attrs;emit;slots三个组件的property)
setup(props,context){
}
1、扩展:父组件通过属性传的值在子组件中的各个部分的获取:
①:props:通过父传子的方式直接获取到值
②:setup(props, context){} 方法中的props只能拿到选项props中已经定义的属性;
③:setup(props, { attrs, emit, slots}){} 方法中的attrs只能拿到未在选项props中定义的属性;
④:通过{ proxy } = getCurrentInstance(); proxy.attrs也只能拿到未在选项props中定义的属性;
2、context:非响应式的对象;包含了组件暴露的三个property:
context.attrs:传入组件中但是未被props接收的对象。
context.emit:用于触发当前组件实例上的传值事件。
context.slots:用来访问被插槽分发的内容(一般用于使用渲染函数来书写一个组件时)
Vue3.x中重写的v-model
用例:Vue3.x重写了v-model的实现方式,以适用用绑定多个v-model
①:单个数据实现数据双向绑定
<my-components v-model="msg"></my-components>
// 等价于
<my-components :modelValue="msg" @update:modelValue="value=$event"></my-components>
// myComponents组件中接收绑定数据和触发数据改变
props: { modelValue: String }; // 获取数据
setup(props, { emit }) {
emit('update:modelValue', 'newValue'); // 触发事件并传值
};
②:多个数据实现数据双向绑定
<my-components v-model:msg="msg" v-model:name="name"></my-components>
// 等价于
<my-components :msg="msg" @update:msg="value=$event" :name="name" @update:name="name=$event"></my-components>
// myComponents组件中接收绑定数据和触发数据改变
props: { msg: String, name: String }; // 获取数据
setup(props, { emit }) {
emit('update:msg', 'newValue'); // 触发事件并传值
emit('update:name', 'newValue'); // 触发事件并传值
};
插槽修改
vue2写法
<div slot="footer">
<el-button size="small" @click="cancelBtn()">取 消</el-button>
<el-button size="small" type="primary" @click="confirmSubmit">确 定</el-button>
</div>
vue3写法
<template #footer>
<div>
<el-button size="small" @click="cancelBtn()">取 消</el-button>
<el-button size="small" type="primary" @click="confirmSubmit">确 定</el-button>
</div>
</template>
vue3 Watch 更新
watch(
() => props.cloudTipsMessage, //监听对象
(newValue, oldValue) => {
if (newValue === '视频') {
reactiveData.fileMap = ['.mp4']
reactiveData.tipsMessage = '.mp4'
} else if (newValue === '音频') {
reactiveData.fileMap = ['.mp3']
reactiveData.tipsMessage = '.mp3'
} else if (newValue === 'PDF') {
reactiveData.fileMap = ['.pdf']
reactiveData.tipsMessage = '.pdf'
} else if (newValue === '文档') {
reactiveData.fileMap = ['.xls', '.xlsx', '.doc', '.docx', '.ppt', '.pptx']
reactiveData.tipsMessage = '.xls,.xlsx,.doc,.docx,.ppt,.pptx'
}
},
{
deep: true // 深度监听的参数
}
)
使用echarts
按需引用,并且挂载方式和vue2(var myChart = this.$echarts.init(this.$refs['pieChart']))有点差别,
不再使用this.$echarts,并且按需引入
<template>
<div id="pieChart" style="width: 100%; height: 400px" />
</template>
<script setup>
import { onMounted } from 'vue'
import * as echarts from 'echarts'
const props = defineProps({
courseData: { type: Array, default: () => [] },
legendData: { type: Array, default: () => [] },
courseTotal: { type: Number, default: 0 }
})
onMounted(() => {
drawPie()
})
function drawPie() {
var myChart = echarts.init(document.getElementById('pieChart'))
var option = {
tooltip: {
trigger: 'item',
formatter: '{b}: {c} ({d}%)'
},
color: ['#3AA0FF', '#4DCB73', '#ee6f3d', '#FAAD14', '#42c7df'], // 饼图颜色
legend: {
orient: 'vertical',
right: 40,
bottom: 30,
data: props.legendData
},
series: [
{
name: '总课程数', // 配置formatter时候会用到(就是{a})
type: 'pie',
radius: ['45%', '66%'], // 配置饼图和环图的内圆和外圆的大小
center: ['40%', '50%'], // 配置图形的位置,前面一个是x轴,后面一个是y轴,'50%'代表是水平居中
avoidLabelOverlap: false,
label: {
show: false,
position: 'center',
fontSize: '16',
fontWeight: 'bold',
formatter: `{a}\n${props.courseTotal}`
},
data: props.courseData
}
]
}
// 设置成功
myChart.setOption(option)
window.onresize = function () {
myChart.resize()
}
}
</script>
<style scoped>
</style>
引入Treeselect
import Treeselect from 'vue3-treeselect'
import 'vue3-treeselect/dist/vue3-treeselect.css'
不再是vue2中的(按照vue2引入会报错)
import Treeselect from '@riophae/vue-treeselect'
import '@riophae/vue-treeselect/dist/vue-treeselect.css'