reactive的一些补充,先看代码:
  
   - 
    
     
    
    
     
      <template>
     
    
- 
    
     
    
    
       
      <div>
     
    
- 
    
     
    
    
         
      <p>{{state}}
      </p>
     
    
- 
    
     
    
    
         
      <button @click="fn">reactive
      </button>
     
    
- 
    
     
    
    
       
      </div>
     
    
- 
    
     
    
    
     
      </template>
     
    
- 
    
     
    
    
     
      <script>
      
     
    
- 
    
     
    
    
     
      import { reactive, toRaw } 
      from 
      "vue";
     
    
- 
    
     
    
    
     
      export 
      default {
     
    
- 
    
     
    
    
     
        setup() {
     
    
- 
    
     
    
    
         
      let obj = { 
      name: 
      "zs", 
      age: 
      18 };
     
    
- 
    
     
    
    
         
      let state = reactive(obj);
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
         
      function fn() {
     
    
- 
    
     
    
    
     
            obj.name = 
      "ls";
     
    
- 
    
     
    
    
           
      console.log(
      "obj", obj);
     
    
- 
    
     
    
    
           
      console.log(
      "state", state);
     
    
- 
    
     
    
    
     
          }
     
    
- 
    
     
    
    
         
      return { state, fn };
     
    
- 
    
     
    
    
     
        },
     
    
- 
    
     
    
    
     
      };
     
    
- 
    
     
    
    
     
      </script>
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
      
     
    
页面打印效果:

我们可以看出改变obj数据吗,state也会跟着改变,但是UI界面却没有刷新,这个是什么问题呢?
我们先看 obj 和 state 的关系
obj和state:引用关系,state的本质是一个Proxy对象,在这个Proxy对象中引用了obj
-  直接修改obj是无法触发UI界面更新的 
-  只有通过包装之后的对象来修改,才会触发界面更新 
通过改变包装之后的state改变数据:
  
   - 
    
     
    
    
     
      <template>
     
    
- 
    
     
    
    
       
      <div>
     
    
- 
    
     
    
    
         
      <p>{{state}}
      </p>
     
    
- 
    
     
    
    
         
      <button @click="fn">reactive
      </button>
     
    
- 
    
     
    
    
       
      </div>
     
    
- 
    
     
    
    
     
      </template>
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
     
      <script>
      
     
    
- 
    
     
    
    
     
      import { reactive, toRaw } 
      from 
      "vue";
     
    
- 
    
     
    
    
     
      export 
      default {
     
    
- 
    
     
    
    
     
        setup() {
     
    
- 
    
     
    
    
         
      let obj = { 
      name: 
      "zs", 
      age: 
      18 };
     
    
- 
    
     
    
    
         
      let state = reactive(obj);
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
         
      function fn() {
     
    
- 
    
     
    
    
           
      // obj.name = "ls";
     
    
- 
    
     
    
    
     
            state.name = 
      "woshinibaba";
     
    
- 
    
     
    
    
           
      console.log(
      "obj", obj);
     
    
- 
    
     
    
    
           
      console.log(
      "state", state);
     
    
- 
    
     
    
    
     
          }
     
    
- 
    
     
    
    
         
      return { state, fn };
     
    
- 
    
     
    
    
     
        },
     
    
- 
    
     
    
    
     
      };
     
    
- 
    
     
    
    
     
      </script>
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
      
     
    
效果如下:我们可以看到 obj 和 state 数据都发生了改变,UI界面也更新了

使用toRaw:
  
   - 
    
     
    
    
     
      <template>
     
    
- 
    
     
    
    
       
      <div>
     
    
- 
    
     
    
    
         
      <p>{{state}}
      </p>
     
    
- 
    
     
    
    
         
      <button @click="fn">reactive
      </button>
     
    
- 
    
     
    
    
       
      </div>
     
    
- 
    
     
    
    
     
      </template>
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
     
      <script>
      
     
    
- 
    
     
    
    
     
      import { reactive, toRaw } 
      from 
      "vue";
     
    
- 
    
     
    
    
     
      export 
      default {
     
    
- 
    
     
    
    
     
        setup() {
     
    
- 
    
     
    
    
         
      let obj = { 
      name: 
      "zs", 
      age: 
      18 };
     
    
- 
    
     
    
    
         
      let state = reactive(obj);
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
         
      let obj2 = toRaw(state)
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
         
      console.log(
      "obj==obj2",obj===obj2)
     
    
- 
    
     
    
    
         
      function fn() {
     
    
- 
    
     
    
    
           
      // obj.name = "ls";
     
    
- 
    
     
    
    
         
      // state.name = "woshinibaba";
     
    
- 
    
     
    
    
           
      console.log(
      "obj", obj);
     
    
- 
    
     
    
    
           
      console.log(
      "state", state);
     
    
- 
    
     
    
    
           
      console.log(
      "obj2", obj2);
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
     
          }
     
    
- 
    
     
    
    
         
      return { state, fn };
     
    
- 
    
     
    
    
     
        },
     
    
- 
    
     
    
    
     
      };
     
    
- 
    
     
    
    
     
      </script>
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
      
     
    

我们可以看出 obj2 和 obj是一样的,也就是说通过toRaw拿到了state的原始数据 obj
我们修改obj2的值:
  
   - 
    
     
    
    
     
      <template>
     
    
- 
    
     
    
    
       
      <div>
     
    
- 
    
     
    
    
         
      <p>{{state}}
      </p>
     
    
- 
    
     
    
    
         
      <button @click="fn">reactive
      </button>
     
    
- 
    
     
    
    
       
      </div>
     
    
- 
    
     
    
    
     
      </template>
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
     
      <script>
      
     
    
- 
    
     
    
    
     
      import { reactive, toRaw } 
      from 
      "vue";
     
    
- 
    
     
    
    
     
      export 
      default {
     
    
- 
    
     
    
    
     
        setup() {
     
    
- 
    
     
    
    
         
      let obj = { 
      name: 
      "zs", 
      age: 
      18 };
     
    
- 
    
     
    
    
         
      let state = reactive(obj);
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
         
      let obj2 = toRaw(state);
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
         
      console.log(
      "obj==obj2", obj === obj2);
     
    
- 
    
     
    
    
         
      function fn() {
     
    
- 
    
     
    
    
           
      // obj.name = "ls";
     
    
- 
    
     
    
    
           
      // state.name = "woshinibaba";
     
    
- 
    
     
    
    
     
            obj2.name = 
      "woshinidie";
     
    
- 
    
     
    
    
           
      console.log(
      "obj", obj);
     
    
- 
    
     
    
    
           
      console.log(
      "state", state);
     
    
- 
    
     
    
    
           
      console.log(
      "obj2", obj2);
     
    
- 
    
     
    
    
     
          }
     
    
- 
    
     
    
    
         
      return { state, fn };
     
    
- 
    
     
    
    
     
        },
     
    
- 
    
     
    
    
     
      };
     
    
- 
    
     
    
    
     
      </script>
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
      
     
    
效果:我们可以看到通过修改 obj2 会同步修改 obj 和 state ,但是UI界面没有更新

我们可以发现 obj2通过toRaw拿到state的原始数据,进行修改,就不会更新界面。
总结:如果我们想修改 state 的内容而又不想引起UI界面的更新,就只需要用
toRaw取出它的 “源值” 进行修改就行了。总之,toRaw是一个用来优化资源加载的方案。
我们看一下 ref 的 toRaw:
我们回顾一下 ref 的本质是什么:
ref本质:reactive    ref(obj) —> reactive({value:obj})ref toRaw代码如下:
  
   - 
    
     
    
    
     
      <template>
     
    
- 
    
     
    
    
       
      <div>
     
    
- 
    
     
    
    
         
      <p>{{oref}}
      </p>
     
    
- 
    
     
    
    
         
      <button @click="fn">reactive
      </button>
     
    
- 
    
     
    
    
       
      </div>
     
    
- 
    
     
    
    
     
      </template>
     
    
- 
    
     
    
    
     
      <script>
      
     
    
- 
    
     
    
    
     
      import { ref, toRaw } 
      from 
      "vue";
     
    
- 
    
     
    
    
     
      export 
      default {
     
    
- 
    
     
    
    
     
        setup() {
     
    
- 
    
     
    
    
         
      let obj3 = { 
      name: 
      "狗子", 
      age: 
      88 };
     
    
- 
    
     
    
    
         
      let oref = ref(obj3);
     
    
- 
    
     
    
    
         
      let toref = toRaw(oref);
     
    
- 
    
     
    
    
         
      function fn() {
     
    
- 
    
     
    
    
           
      console.log(
      "obj3", obj3);
     
    
- 
    
     
    
    
           
      console.log(
      "oref", oref);
     
    
- 
    
     
    
    
           
      console.log(
      "toref", toref);
     
    
- 
    
     
    
    
     
          }
     
    
- 
    
     
    
    
         
      return { oref, fn };
     
    
- 
    
     
    
    
     
        },
     
    
- 
    
     
    
    
     
      };
     
    
- 
    
     
    
    
     
      </script>
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
      
     
    
效果:我们可以看出 和 reactive不一样,这是为什么呢?

根据 ref 的本质可以看出 我们应该去拿 .value ,我们再试一下
  
   - 
    
     
    
    
     
      <template>
     
    
- 
    
     
    
    
       
      <div>
     
    
- 
    
     
    
    
         
      <p>{{oref}}
      </p>
     
    
- 
    
     
    
    
         
      <button @click="fn">reactive
      </button>
     
    
- 
    
     
    
    
       
      </div>
     
    
- 
    
     
    
    
     
      </template>
     
    
- 
    
     
    
    
     
      <script>
      
     
    
- 
    
     
    
    
     
      import { ref, toRaw } 
      from 
      "vue";
     
    
- 
    
     
    
    
     
      export 
      default {
     
    
- 
    
     
    
    
     
        setup() {
     
    
- 
    
     
    
    
         
      let obj3 = { 
      name: 
      "狗子", 
      age: 
      88 };
     
    
- 
    
     
    
    
         
      let oref = ref(obj3);
     
    
- 
    
     
    
    
         
      let toref = toRaw(oref.value);
     
    
- 
    
     
    
    
         
      console.log(
      "obj3 == toref",obj3 == toref)
     
    
- 
    
     
    
    
         
      function fn() {
     
    
- 
    
     
    
    
           
      console.log(
      "obj3", obj3);
     
    
- 
    
     
    
    
           
      console.log(
      "oref", oref);
     
    
- 
    
     
    
    
           
      console.log(
      "toref", toref);
     
    
- 
    
     
    
    
     
          }
     
    
- 
    
     
    
    
         
      return { oref, fn };
     
    
- 
    
     
    
    
     
        },
     
    
- 
    
     
    
    
     
      };
     
    
- 
    
     
    
    
     
      </script>
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
      
     
    

我们需要注意的几个点:
- 如果想通过toRaw拿到ref类型的原始数据(创建时传入的那个数据)
- 那么就必须明确告诉toRaw方法,要获取的还是 .value 的值
- 因为经过vue处理之后, .value 中保存的才是当初创建时传入的那个原始数据
下面我们来修改一下 ref 的toRaw :
  
   - 
    
     
    
    
     
      <template>
     
    
- 
    
     
    
    
       
      <div>
     
    
- 
    
     
    
    
         
      <p>{{oref}}
      </p>
     
    
- 
    
     
    
    
         
      <button @click="fn">reactive
      </button>
     
    
- 
    
     
    
    
       
      </div>
     
    
- 
    
     
    
    
     
      </template>
     
    
- 
    
     
    
    
     
      <script>
      
     
    
- 
    
     
    
    
     
      import { ref, toRaw } 
      from 
      "vue";
     
    
- 
    
     
    
    
     
      export 
      default {
     
    
- 
    
     
    
    
     
        setup() {
     
    
- 
    
     
    
    
         
      let obj3 = { 
      name: 
      "狗子", 
      age: 
      88 };
     
    
- 
    
     
    
    
         
      let oref = ref(obj3);
     
    
- 
    
     
    
    
         
      let toref = toRaw(oref.value);
     
    
- 
    
     
    
    
         
      console.log(
      "obj3 == toref", obj3 == toref);
     
    
- 
    
     
    
    
         
      function fn() {
     
    
- 
    
     
    
    
           
      console.log(
      "obj3", obj3);
     
    
- 
    
     
    
    
           
      console.log(
      "oref", oref);
     
    
- 
    
     
    
    
     
            toref.name = 
      "我是你爹";
     
    
- 
    
     
    
    
           
      console.log(
      "toref", toref);
     
    
- 
    
     
    
    
     
          }
     
    
- 
    
     
    
    
         
      return { oref, fn };
     
    
- 
    
     
    
    
     
        },
     
    
- 
    
     
    
    
     
      };
     
    
- 
    
     
    
    
     
      </script>
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
      
     
    

我们可以看出,修改toref 会修改 oref 的数据,obj3没有变化,因为我们拿到的是oref的 .value, 我们可以看到界面没有更新
此时,和 reactive 的 toRaw 效果就完全一致了
总结:
ref/reactive 数据类型特点:
每次修改都会被追踪,都会更新UI界面,但是这样其实是非常消耗性能的
所以如果我们有一些操作不需要被追踪,不需要更新UI界面,那么这个时候,我们就可以通过toRaw方法拿到它的原始数据
对原始数据进行修改,这样就不会被追踪,这样就不会更新UI界面,这样性能就变好了
附录全部代码:
  
   - 
    
     
    
    
     
      <template>
     
    
- 
    
     
    
    
       
      <div>
     
    
- 
    
     
    
    
         
      <p>{{state}}
      </p>
     
    
- 
    
     
    
    
         
      <button @click="myfun">changeRaw
      </button>
     
    
- 
    
     
    
    
         
      <hr>
     
    
- 
    
     
    
    
         
      <p>{{oref}}
      </p>
     
    
- 
    
     
    
    
         
      <button @click="fn">ref
      </button>
     
    
- 
    
     
    
    
       
      </div>
     
    
- 
    
     
    
    
     
      </template>
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
     
      <script>
      
     
    
- 
    
     
    
    
     
      import { ref, toRaw, reactive } 
      from 
      "vue";
     
    
- 
    
     
    
    
     
      export 
      default {
     
    
- 
    
     
    
    
       
      name: 
      "App",
     
    
- 
    
     
    
    
     
        setup() {
     
    
- 
    
     
    
    
         
      let obj = {
     
    
- 
    
     
    
    
           
      name: 
      "csl",
     
    
- 
    
     
    
    
           
      age: 
      18,
     
    
- 
    
     
    
    
     
          };
     
    
- 
    
     
    
    
         
      /*
     
    
- 
    
     
    
    
     
       ref/reactive 数据类型特点:
     
    
- 
    
     
    
    
     
       每次修改都会被追踪,都会更新UI界面,但是这样其实是非常消耗性能的
     
    
- 
    
     
    
    
     
       所以如果我们有一些操作不需要被追踪,不需要更新UI界面,那么这个时候,我们就可以通过toRaw方法拿到它的原始数据
     
    
- 
    
     
    
    
     
       对原始数据进行修改,这样就不会被追踪,这样就不会更新UI界面,这样性能就变好了
     
    
- 
    
     
    
    
     
       */
     
    
- 
    
     
    
    
         
      let state = reactive(obj);
     
    
- 
    
     
    
    
         
      // state 和 obj 关系 引用关系 ,state的本质是一个Proxy对象,在这个Proxy对象中引用了obj
     
    
- 
    
     
    
    
         
      let obj2 = toRaw(state);
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
         
      // console.log("obj==state", obj === state, obj === obj2); //false true
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
         
      function myfun() {
     
    
- 
    
     
    
    
           
      // 如果直接修改obj是无法触发界面更新的
     
    
- 
    
     
    
    
           
      // 只有通过包装之后的对象来修改,才会触发界面更新
     
    
- 
    
     
    
    
           
      // obj.name = "zsssss"
     
    
- 
    
     
    
    
             
      console.log(obj)
      //{name: "zsssss", age: 18}
     
    
- 
    
     
    
    
           
      // state.name = "zsss";
     
    
- 
    
     
    
    
           
      // console.log(state);//{name: "zsssss", age: 18}
     
    
- 
    
     
    
    
     
            obj2.name = 
      "zssss";
     
    
- 
    
     
    
    
           
      console.log(
      "obj2", obj2);
     
    
- 
    
     
    
    
           
      console.log(state);
     
    
- 
    
     
    
    
     
          }
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
         
      let obj3 = { 
      name: 
      "狗子", 
      age: 
      88 };
     
    
- 
    
     
    
    
         
      /*
     
    
- 
    
     
    
    
     
       1、ref本质:reactive
     
    
- 
    
     
    
    
     
       ref(obj) ——> reactive({value:obj})
     
    
- 
    
     
    
    
     
       * */
     
    
- 
    
     
    
    
         
      let oref = ref(obj3);
     
    
- 
    
     
    
    
         
      // 注意点:如果想通过toRaw拿到ref类型的原始数据(创建时传入的那个数据)
     
    
- 
    
     
    
    
         
      // 那么就必须明确告诉toRaw方法,要获取的还是 .value 的值
     
    
- 
    
     
    
    
         
      // 因为经过vue处理之后, .value 中保存的才是当初创建时传入的那个原始数据
     
    
- 
    
     
    
    
         
      // let toref = toRaw(oref)
     
    
- 
    
     
    
    
         
      let toref = toRaw(oref.value)
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
         
      function fn(){
     
    
- 
    
     
    
    
             
      console.log(
      "obj3",obj3)
     
    
- 
    
     
    
    
             
      console.log(
      "oref",oref)
     
    
- 
    
     
    
    
     
              toref.name = 
      "lllkkkk"
     
    
- 
    
     
    
    
             
      console.log(
      "toref",toref)
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
     
          }
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
         
      return {
     
    
- 
    
     
    
    
     
            state,
     
    
- 
    
     
    
    
     
            myfun,
     
    
- 
    
     
    
    
     
            oref,
     
    
- 
    
     
    
    
     
            fn
     
    
- 
    
     
    
    
     
          };
     
    
- 
    
     
    
    
     
        },
     
    
- 
    
     
    
    
     
      };
     
    
- 
    
     
    
    
     
      </script>
     
    
markRaw
有的时候,我们希望某些数据是无法被改变的。
markRaw
显式标记一个 对象 (不能是简单类型) 为“永远不会转为响应式代理”,函数返回这个对象本身。
  
   - 
    
     
    
    
     
      const foo = markRaw({})
     
    
- 
    
     
    
    
     
      console.log(isReactive(reactive(foo))) 
      // false
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
     
      // 如果被 markRaw 标记了,即使在响应式对象中作属性,也依然不是响应式的
     
    
- 
    
     
    
    
     
      const bar = reactive({ foo })
     
    
- 
    
     
    
    
     
      console.log(isReactive(bar.foo)) 
      // false
     
    
  
   - 
    
     
    
    
     
      <template>
     
    
- 
    
     
    
    
       
      <div>
     
    
- 
    
     
    
    
         
      <p>{{ state }}
      </p>
     
    
- 
    
     
    
    
         
      <button @click="fun">click
      </button>
     
    
- 
    
     
    
    
       
      </div>
     
    
- 
    
     
    
    
     
      </template>
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
     
      <script>
      
     
    
- 
    
     
    
    
     
      import { reactive, markRaw } 
      from 
      "vue";
     
    
- 
    
     
    
    
     
      export 
      default {
     
    
- 
    
     
    
    
     
        setup() {
     
    
- 
    
     
    
    
         
      let obj = { 
      name: 
      "我是你爹", 
      age: 
      22 };
     
    
- 
    
     
    
    
     
          obj = markRaw(obj)
     
    
- 
    
     
    
    
         
      let state = reactive(obj);
     
    
- 
    
     
    
    
         
      function fun() {
     
    
- 
    
     
    
    
     
            state.name = 
      "叫爸爸";
     
    
- 
    
     
    
    
           
      console.log(state)
     
    
- 
    
     
    
    
     
          }
     
    
- 
    
     
    
    
         
      return { state, fun };
     
    
- 
    
     
    
    
     
        },
     
    
- 
    
     
    
    
       
      methods: {},
     
    
- 
    
     
    
    
     
      };
     
    
- 
    
     
    
    
     
      </script>
     
    
- 
    
     
    
    
      
     
    
- 
    
     
    
    
      
     
    

转载:https://blog.csdn.net/csl125/article/details/116235214
