vue3 setup 使用 和 ref,reactive 响应式引用的用法和原理

https://v3.cn.vuejs.org/guide/composition-api-setup.html#setup

 

setup在created实例初始化之前。  所以呢  在里面不能用 this啊,他肯定找不到的。

直接返回的数据,全局也是拿的到的。

 

使用 setup 函数时,它将接收两个参数:

  1. props
  2. context

让我们更深入地研究如何使用每个参数.

 


 

  ref,reactive 响应式引用的用法和原理

如果在setup 返回的数据改变后,是不会响应式的,所以用到ref:

响应式原理:通过 proxy 对数据进行封装,当数据变化时,触发模版等内容的更新

那么 ref 处理基础类型的数据,记住啊 是基础类型,什么什么对象、数组不是用ref,使用ref的值的话,是用ref.value, 但是如果在html代码中使用,不用带.value,因为VUE 自动识别。

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>study</title>
        <script src="https://unpkg.com/vue@next"></script>
    </head>
    <body>
        <div id="root"></div>
    </body>
    <script>
        const app = Vue.createApp({
            template: `
      <div>{{name}}</div>
    `,
            setup(props, context) {
                // 引入ref
                const {
                    ref
                } = Vue;
                //proxy, 标识咸瑜 为响应式数据, '咸瑜'变成 proxy({value: '咸瑜'}) 这样的一个响应式引用
                let name = ref('咸瑜');
                setTimeout(() => {
                    // 注意这里使用是用了 name.value ,因为使用了 ref
                    name.value = '大咸鱼(已改变)'
                }, 2000)
                return {
                    name
                }
            }
        });
        const vm = app.mount('#root');
    </script>
</html>
View Code

自己看列子,例子中2S后 “咸鱼” 变为 “大咸鱼” ,其中用到了ref,如果不用 ,那么你就别想响应式。 原理就是 proxy ,底层自己会操作。

 


 reactive :

和ref的一样,使用详细看下面代码怎么用的即可: 下面数组和对象都定义了。

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>study</title>
        <script src="https://unpkg.com/vue@next"></script>
    </head>
    <body>
        <div id="root"></div>
    </body>
    <script>
        // reactive 处理非基础类型的数据
        const app = Vue.createApp({
            template: `
        <div>{{nameObj.name}}</div>
      `,
            setup(props, context) {
                // 引入 reactive
                const {
                    reactive,
                } = Vue;
                // 定义nameObj 是个对象。
                const nameObj = reactive({
                    name: '咸瑜'
                });
                // 2S 后改变对象的值。
                setTimeout(() => {
                    nameObj.name = '菜鸟小咸瑜'
                }, 2000)
                
                return{
                    nameObj
                }
            }
        });
        const vm = app.mount('#root');
    </script>
</html>
对象 Code
<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>study</title>
        <script src="https://unpkg.com/vue@next"></script>
    </head>
    <body>
        <div id="root"></div>
    </body>
    <script>
        // reactive 处理非基础类型的数据
        const app = Vue.createApp({
            template: `
        <div>{{numArr[0]}}</div>
      `,
            setup(props, context) {
                // 引入 reactive
                const {
                    reactive,
                } = Vue;
                // 定义numArr 是个数组。  数组也是一样的。
                const numArr = reactive([123]);
                // 2S 后改变数组元素[0] 为 456
                setTimeout(() => {
                    numArr[0] = 456
                }, 2000)
                return{
                    numArr
                }
            }
        });
        const vm = app.mount('#root');
    </script>
</html>
数组Code

 

新的玩意,心得开始(开死)....


 除了上面2个,如果你想让 对象或数组是只读的话,那么vue 还有个玩意叫 readonly :

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>study</title>
        <script src="https://unpkg.com/vue@next"></script>
    </head>
    <body>
        <div id="root"></div>
    </body>
    <script>
        // readonly 标识为只读的,
        const app = Vue.createApp({
            template: `
        <div>{{copyArr[0]}}</div>
      `,
            setup(props, context) {
                // 引入 
                const {
                    reactive,
                    readonly
                } = Vue;
                const numArr = reactive([123]);
                // 把它标识为只读的,他会返回一份不可以被修改的numArr【copyArr】
                const copyArr = readonly(numArr)
                setTimeout(() => {
                    // 修改之前的是完全没问题的。。。
                    numArr[0] = 456
                    // 修改copyArr的第一个元素为456 【会报警】
                    copyArr[0] = 456
                }, 2000)
                // 返回
                return {
                    copyArr
                }
            }
        });
        const vm = app.mount('#root');
    </script>
</html>
readonlyTest Code

 

 这个就是修改copyArr[0] = 456 时候的警告了。

 


 

如果你有这样的需求:解构然后返回,但你解构后的变量肯定也不是响应式的,那你就可以用 toRefs了:

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>study</title>
        <script src="https://unpkg.com/vue@next"></script>
    </head>
    <body>
        <div id="root"></div>
    </body>
    <script>
        // 注意看 这里直接调用name
        const app = Vue.createApp({
            template: `
        <div>{{name}}</div>
      `,
            setup(props, context) {
                // 引入 
                const {
                    reactive,
                    readonly,
                    toRefs
                } = Vue;
                
                const personObj = reactive({
                    name:"咸鱼",
                    age:18
                })
                const {name} = toRefs(personObj);
                // 返回
                return { 
                    name
                }
            }
        });
        const vm = app.mount('#root');
    </script>
</html>
View Code

其实他的原理就是:

把 personOBJ 转变成:(name : proxy({  value : "咸鱼" }))

所以呢,这里直接返回name,也是可以直接渲染【响应式】。

posted @ 2022-04-04 11:15  咸瑜  阅读(422)  评论(0编辑  收藏  举报