测试数据的响应性
子组件代码:
js部分:
import {ref,toRefs,reactive,toRef} from 'vue';
name: "MyTest",
//props 必不可少 最好写成对象
// props:['p_data'],
props:{
'parent-data':{
type:Number,
required:true,
},
'test_again':{
type:String,
required: true
}
},
setup(props,{attrs,slots,emit,expose}){
//父组件传递数据
console.log(props)
//父组件传递的属性
// console.log(context.attrs)
// console.log(context.slots)
// console.log(context.emit)
// console.log(context.expose)
// 因为context是普通的JS对象,所以支持直接解构
console.log(attrs);
console.log(slots);
console.log(emit);
console.log(expose);
//跟上面的一样 但是有点搞不懂它究竟可以干啥???
let normal_a = 5;
let normal_b = 6;
const ref_a = ref(15);
const ref_b = ref(16);
const normal_obj_a = {test_num1:10,test_num2:20}
// const ref_obj_b = toRefs({test_num_ref1:18,test_num_ref2:28})
//第一版这样写之后 报错了 :
// toRefs() expects a reactive object but received a plain one.
//第二版
const ref_obj_reactive = reactive({test_num_ref1:18,test_num_ref2:28})
const ref_obj_b = toRefs(ref_obj_reactive)
function calculateFuc(){
normal_a++;
normal_b--;
ref_a.value++;
ref_b.value--;
normal_obj_a.test_num1++;
ref_obj_b.test_num_ref1.value++;
}
//父组件传数据测试=======================================
// const {parentData }= props
// console.log(parentData)
//直接解构 不用toRef 报错
//Getting a value from the `props` in root scope of `setup()` will cause the value to lose reactivity vue/no-setup-props-destructure
//props 是响应性的切记不要直接解构
const parentData = toRef(props,'parentData')
console.log(parentData.value)
//得出结论:起初我以为单个值传递给props的时候,不需要解构,验证之后 想法错误 不管父级组件传来的数据是什么类型,props为了响应性都给套了有个外壳
//关于暴露
return{
normal_a,
normal_b,
ref_a,
ref_b,
normal_obj_a,
ref_obj_b,
calculateFuc,
parentData,
}
},
template部分:
<fieldset id="my-test">
<legend>这是自己搞的测试单文件</legend>
<p><button style="border: 2px solid red" @click="calculateFuc">点击计算函数</button></p>
<ol>
<li>normal_a:==>{{normal_a}}</li>
<li>normal_b:==>{{normal_a}}</li>
<li>ref_a:==>{{ref_a}}</li>
<li>ref_b:==>{{ref_b}}</li>
<li>normal_obj_a.test_num1:==>{{normal_obj_a.test_num1}}</li>
<li>ref_obj_b:==>{{ref_obj_b.test_num_ref1}}</li>
</ol>
<hr>
<ol>
<li>定义数据得出结论,单一数据通过setup返回之后,到渲染的时候单纯的就说一个数字,想要保持响应性,利用ref + value</li>
<li>数组的话</li>
</ol>
<h4>父组件传递过来的数据(单个值的情况)为:{{parentData}}</h4>
<hr>
<h5>测试一下关于插槽的知识点</h5>
<slot name="default" :test_slot="ref_b"></slot>
<slot name="sum"></slot>
</fieldset>
css部分
<style scoped>
#my-test{
border:2px solid #2c3e50 ;
background-color: #ddd;
}
</style>
父组件部分
js代码
<script>
import { ref} from 'vue'
import SetupComponent from './components/setup'
import MyTest from "./components/my-test";
export default {
name: "combined-main.vue",
// 我开始发挥啦~
data(){
return{
p_a:100,
// 向子级组件传递的不管是对象还是数值 都需要解构
p_attr:'爹给儿的属性',
p_test_context:'如果在子组件的props中引入,那么该数据就应该出现在子组件中的setup的props而不是attrs'
}
},
components: {
SetupComponent,
MyTest,
},
setup(){
const childrenRef = ref(null)
return{
childrenRef
}
},
}
</script>
template部分
<template>
<h1>组合API页</h1>
<p>测试在一个页面上添加一个子组件,它的文件结构!</p>
<fieldset>
<legend>这是example1的父组件</legend>
<div id="example1">
<p>这里边的标签是正常使用的!</p>
<p>测试 子组件, 添加一个带有 setup 函数的子组件</p>
<setup-component ref="childrenRef"></setup-component>
<p>从子组件通过ref访问到的数据{{childrenRef}}</p>
<!-- 以下是我自己要写的测试my-test.vue-->
<MyTest :parent-data="p_a" :test_attr=" p_attr" :test_again="p_test_context">
<!-- 测一下我比较迷糊的插槽-->
<template v-slot:default="getChildProps" >
<div style="background-color:pink;width: 300px;border: 3px dashed orange">
<p>我是在父组件中给子组件添加的插槽,想测试一下子组件如何向父组件通过插槽传递数据的</p>
<p>子组件通过插槽传过来的数据为:<span style="color: cornsilk">{{getChildProps.test_slot}}</span></p>
</div>
</template>
<!-- 注释插槽-->
<template v-slot:sum>
<ol>
<li>父传子 千年不变的 规律 找props 并且为了其响应性 不可以在子组件中直接解构props 也不可以更改数据</li>
<li>子传父 目前有三种方式
<ol>
<li>从父组件定义一个函数,在子组件emit中传入,执行的时候传递数据</li>
<li>slot方式子组件在slot标签中任意定义属性,最后父组件的template中 直接插槽名字.属性</li>
<li>还有一种就是ref,通过子组件利用expose暴露,接着父组件定义ref=attrname,接着父组件的setup 声明 attrname=ref(null),返回attrname 然后父组件就可以用到子组件传来的数据啦</li>
</ol>
</li>
</ol>
</template>
</MyTest>
<p><button style="background-color: #42b983;border: 3px solid #dddddd" @click="p_a++">操作往子组件传递的数p_a:{{p_a}}</button></p>
<h5>经过测试 子组件用toRef()解构父组件传递的数据成功,如果不用toRef 直接报错 说失去响应性</h5>
</div>
</fieldset>
</template>
部分知识点:
在 setup
中你应该避免使用 this
,因为它不会找到组件实例。setup
的调用发生在 data
property、computed
property 或 methods
被解析之前,所以它们无法在 setup
中被获取。
因为 setup
是围绕 beforeCreate
和 created
生命周期钩子运行的,所以不需要显式地定义它们。换句话说,在这些钩子中编写的任何代码都应该直接在 setup
函数中编写。
在 Vue 3.0 中,我们可以通过一个新的 ref
函数使任何响应式变量在任何地方起作用
ref
接收参数并将其包裹在一个带有 value
property 的对象中返回,然后可以使用该 property 访问或更改响应式变量的值:
provide&inject
provide 有两个参数 :name
&& value
inject 参数也有两个。只不过第二个是可选的。name
value(默认属性值)
为了增加 provide 值和 inject 值之间的响应性,我们可以在 provide
值时使用 ref
或者reactive
,如果想要对提供的信息进行修改的话,一般在provide方进行修改,涉及到inject方动作影响provide方提供的数据的情况,那么官方建议“有时我们需要在注入数据的组件内部更新 inject 的数据。在这种情况下,我们建议 provide 一个方法来负责改变响应式 property。”
最后,如果要确保通过 provide
传递的数据不会被 inject 的组件更改,我们建议对提供者的 property 使用 readonly
export default {
components: {
MyMarker
},
setup() {
const location = ref('North Pole')
const geolocation = reactive({
longitude: 90,
latitude: 135
})
const updateLocation = () => {
location.value = 'South Pole'
}
provide('location', readonly(location))
provide('geolocation', readonly(geolocation))
provide('upd