最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • 「快速学习系列」我熬夜整理了Vue3.x响应性API

    正文概述 掘金(Vam的金豆之路)   2021-02-16   535

    前言

    Vue3.x正式版发布已经快半年了,相信大家也多多少少也用Vue3.x开发过项目。那么,我们今天就整理下Vue3.x中的响应性API。

    响应性API

    reactive

    作用: 创建一个响应式数据。

    本质: 传入数据(复杂类型:数组和json对象)包装成一个Proxy对象。如果传入其他对象,默认情况下修改对象,界面不会自动更新,如果想更新,可以通过重新赋值(创建一个新的对象)的方式。

    <template>
      <div class="reactive">
        <button @click="fn">点击</button>
        <p>{{ state }}</p>
        <button @click="fn1">点击1</button>
        <p>{{ timeState }}</p>
      </div>
    </template>
    
    <script>
    import { reactive } from "vue";
    export default {
      name: "Reactive",
      setup() {
        let state = reactive({
          name: "123",
        });
        function fn() {
          console.log(state);
          state.name = "456";
        }
    
        let timeState = reactive({
          time: new Date(),
        });
    
        function fn1() {
          const newTime = new Date(timeState.time.getTime());
          newTime.setDate(timeState.time.getDate() + 1);
          timeState.time = newTime;
          console.log(timeState.time);
        }
    
        return {
          state,
          fn,
          timeState,
          fn1,
        };
      },
    };
    </script>
    
    

    ref

    作用: 创建一个响应式数据。

    本质: 其实还是reactive。当我们给ref函数传递一个值(一般是简单类型)之后,ref函数底层会自动将ref转换成reactive,即ref(123) => reactive({value:123}),所以修改对应的值必须在后面加上.value。 **注意点:**在template标签内不用加.value

    <template>
      <div>
        <button @click="fn">点击</button>
        <p>{{state}}</p>
        <button @click="fn1">点击1</button>
        <p>{{arrState}}</p>
      </div>
    </template>
    
    <script>
    import {ref} from "vue";
    export default {
      name:"Ref",
      setup(){
        let state = ref(123);
        function fn () {
          state.value = 345;
        }
        let arrState = ref([]);
        function fn1 (){
          arrState.value.push("1");
        }
        return {
          state,
          fn,
          arrState,
          fn1
        }
      }
    }
    </script>
    

    shallowReactive

    作用: 创建一个响应式 proxy,跟踪其自身 property 的响应性,但不执行嵌套对象的深度响应式转换 (暴露原始值)。

    本质: 对于嵌套对象不做响应,值跟踪自身的第一层property

    <template>
      <div>
        <button @click="fn">点击</button>
        <button @click="fn1">点击1</button>
        <p>{{state}}</p>
      </div>
    </template>
    
    <script>
    import { shallowReactive } from "vue"
    export default {
      name:"ShallowReactive",
      setup(){
        let state = shallowReactive({
          name:"maomin",
          age:{
            number:20
          }
        })
        function fn(){
          state.name = "123"; // 响应性
        }
        function fn1(){
          state.age.number = 23; // 无响应性
        }
        return {
          state,
          fn,
          fn1
        }
      }
    }
    </script>
    

    shallowRef

    作用: 创建一个 ref,它跟踪自己的 .value 更改,但不会使其值成为响应式的。不会将其值转化为Proxy对象。

    <template>
      <div>
        <button @click="fn">点击</button>
        <p>{{ state }}</p>
        <button @click="fn1">点击1</button>
        <p>{{ state1 }}</p>
      </div>
    </template>
    
    <script>
    import { 
      shallowRef, 
      ref, 
      // triggerRef 
    } from "vue";
    export default {
      name: "ShallowRef",
      setup() {
        let state = shallowRef({
          name: "maomin",
        });
        let state1 = ref({});
        function fn() {
          state.value.name = "345";
          console.log(state.value); // {name: "345"}, 但是UI界面不会变。
          // triggerRef(state); // 如果想触发UI界面,可以使用它。
        }
        function fn1() {
          state1.value = {
            name: "123",
          };
          // eslint-disable-next-line no-irregular-whitespace
          console.log(state1.value); // Proxy {name: "123"}
        }
        return {
          state,
          fn,
          state1,
          fn1,
        };
      },
    };
    </script>
    

    readonly

    作用: 获取一个对象 (响应式或纯对象) 或 ref 并返回原始 proxy 的只读 proxy。只读 proxy 是深层的:访问的任何嵌套 property 也是只读的。

    <template>
      <div>
        <button @click="fn">点击</button>
        <p>{{os}}</p>
        <p>{{state}}</p>
      </div>
    </template>
    
    <script>
    import {reactive, readonly} from "vue";
    export default {
      name:"Readonly",
      setup(){
        let state = reactive({
          name:"maomin",
          age:{
            number:18
          }
        })
        let os = readonly(state);
        function fn(){
          os.name = "123";
        }
        return{
          os,
          state,
          fn
        }
      }
    }
    </script>
    

    shallowReadonly

    作用: 创建一个 proxy,使其自身的 property 为只读,但不执行嵌套对象的深度只读转换 (暴露原始值)。

    <template>
      <div>
        <button @click="fn">点击</button>
        <p>{{os}}</p>
        <p>{{state}}</p>
      </div>
    </template>
    
    <script>
    import {
      reactive, 
      shallowReadonly,
      isReadonly
      } from "vue";
    export default {
      name:"ShallowReadonly",
      setup(){
        let state = reactive({
          name:"maomin",
          age:{
            number:18
          }
        })
    
        let os = shallowReadonly(state);
    
        function fn(){
           console.log(isReadonly(os.name)) //false
           os.age.number = 20;
        }
        return{
          state,
          os,
          fn,
        }
      }
    }
    </script>
    

    toRaw

    作用: 响应式对象转普通对象。

    本质: 返回由reactivereadonly 方法转换成响应式代理的普通对象。这是一个还原方法,可用于临时读取,访问不会被代理/跟踪,写入时也不会触发更改。不建议一直持有原始对象的引用。

    <template>
      <div>
        <button @click="fn">点击</button>
        <p>{{state}}</p>
      </div>
    </template>
    
    <script>
    import { reactive, toRaw } from "vue";
    export default {
      name:"ToRaw",
      setup(){
        const obj = {
          name:"maomin"
        };
        let state = reactive(obj);
        function fn(){
          console.log(toRaw(state) === obj); //true
          let obj1 = toRaw(state);
          obj1.name = "123";
          // eslint-disable-next-line no-irregular-whitespace
          console.log(state); // Proxy {name: "123"}. 值虽改变,但是页面没有变化。
        }
    
        return {
          state,
          fn
        }
      }
    }
    </script>
    
    

    markRaw

    作用: 标记一个对象,使其永远不会转换为 proxy。返回对象本身。

    <template>
      <div>
        <button @click="fn">点击</button>
        <p>{{state}}</p>
      </div>
    </template>
    
    <script>
    import {markRaw,reactive} from "vue"
    export default {
      name:"MarkRaw",
      setup(){
        let obj = {name:'maomin', age: 20};
        obj = markRaw(obj);
        let state = reactive(obj);
        function fn(){
          state.name = '123';
          console.log(state); //这里虽然打印出name:123,但是UI界面不会改变。
        }
        return{
          state,
          fn
        }
      }
    }
    </script>
    

    toRef

    如果使用ref,我们修改响应式的数据是不会影响到原始数据的(复制)。 如果使用toRef,我们修改响应式的数据是会影响到原始数据的(引用)。

    作用: 可以用来为源响应式对象上的 property 新创建一个 ref。然后可以将 ref 传递出去,从而保持对其源 property 的响应式连接。

    <template>
      <div>
        <button @click="fn">点击</button>
        <p>{{state}}</p>
        <button @click="fn1">点击1</button>
        <p>{{state1}}</p>
      </div>
    </template>
    
    <script>
    import {reactive, ref, toRef} from "vue"
    export default {
      name:"ToRef",
      setup(){
        let obj = {name:"maomin"};
        let os = reactive(obj);
    
        let state = ref(os.name);
        let state1 = toRef(os,'name');
        // ref
        function fn(){
          state.value = "123";
          console.log(os); // 原始数据不会发生改变
          console.log(state);
        }
        // toRef
        function fn1(){
          state1.value = "345";
          console.log(os); // 原始数据会发生改变
          console.log(state1);
        }
        return {
          state,
          fn,
          state1,
          fn1
        }
      }
    }
    </script>
    

    toRefs

    作用: 将响应式对象转换为普通对象,其中结果对象的每个 property 都是指向原始对象相应 propertyref

    用途: 当从合成函数返回响应式对象时,toRefs 非常有用,这样消费组件就可以在不丢失响应性的情况下对返回的对象进行分解/扩散。

    <template>
      <div>
        <button @click="fn">点击</button>
        <p>{{state}}</p>
        <button @click="fn1">点击1</button>
        <p>{{foo}}</p>
      </div>
    </template>
    
    <script>
    import {reactive, toRefs} from "vue"
    export default {
      name:"ToRefs",
      setup(){
        let obj = {
          name:"maomin",
          age:20
        }
        let os = reactive(obj);
        let state = toRefs(os);
    
        function fn(){
          state.name.value = "123";
          os.name = "234";
          console.log(os);
          console.log(state);
          console.log(state.name.value === os.name); //true
        }
    
        const { foo, bar } = useFeatureX();
      
        function fn1(){
          foo.value = "2";
        }
        return {
          fn,
          state,
          foo,
          bar,
          fn1
        }
      }
    }
    
    
    function useFeatureX() {
      const state = reactive({
        foo: 1
      })
      // 返回时转换为ref
      return toRefs(state)
    }
    </script>
    

    customRef

    作用: 创建一个自定义的 ref,并对其依赖项跟踪和更新触发进行显式控制。它需要一个工厂函数,该函数接收 tracktrigger 函数作为参数,并应返回一个带有 getset 的对象。

    <template>
      <div>
        <button @click="fn">点击</button>
        <p>{{state}}</p>
      </div>
    </template>
    
    <script>
    import {customRef} from "vue";
    
    function myRef(value){
      return customRef((track, trigger)=>{
        return {
          get(){
            track();
            console.log('get',value);
            return value;
          },
          set(newValue){
            console.log('set',newValue);
            value = newValue;
            trigger();
          }
        }
      })
    }
    export default {
      name:"CustomRef",
      setup(){
        let state = myRef(18);
    
        function fn(){
          state.value = 19;
        }
        return {
          state,
          fn
        }
      }
    }
    </script>
    

    computed

    作用: 依赖项变化时,其赋予的值也就相应改变。

    注意点: 直接修改computed是不可以的。

    <template>
      <div>
        <p>{{state}}</p>
        <p>{{os}}</p>
        <button @click="fn">点击</button>
      </div>
    </template>
    
    <script>
    import {computed,ref} from "vue"
    export default {
      name: "Computed",
      setup(){
        let state = ref(12);
        let os = computed(() => state.value + 1);
    
        function fn(){
          state.value = 23; // os的值也会相应改变
          // os.value = 26; // Write operation failed: computed value is readonly
        }
        return{
          state,
          os,
          fn
        }
      }
    }
    </script>
    

    watchEffect

    作用: 在响应式地跟踪其依赖项时立即运行一个函数,并在更改依赖项时重新运行它。

    <template>
      <div>
        <button @click="fn">点击</button>
        <p>{{state}}</p>
        <p>{{state1}}</p>
        <p>{{num}}</p>
      </div>
    </template>
    
    <script>
    import { reactive, ref, watchEffect } from "vue"
    export default {
      name:"WatchEffect",
      setup(){
        let state = ref(0);
        let state1 = reactive({
          name:"maomin"
        })
        let num = 1;
        // 首次运行时会执行它,如果响应依赖项改变时,会重新执行它。
        watchEffect(()=>{
          // console.log(num);
          console.log(state.value);
          console.log(state1);
        })
    
        function fn() {
          state.value = 3;
          state1.name = "123";
          num = 2;
        }
    
        return{
          fn,
          state,
          state1,
          num
        }
      }
    }
    </script>
    

    watch

    作用: 默认情况下,它也是惰性的——即回调仅在侦听源发生更改时调用。

    <template>
      <div>
        <button @click="fn">点击</button>
        <p>{{state}}</p>
        <button @click="fn1">点击1</button>
        <p>{{state1}}</p>
      </div>
    </template>
    
    <script>
    import {reactive, ref, watch} from "vue"
    export default {
      name:"Watch",
      setup(){
    
        // reactive
        let state = reactive({
          name:"maomin"
        })
    
        watch(
          () => state.name,
          (count) =>{
            console.log(count); //123
          }
        )
    
        function fn() {
          state.name = "123";
        }
    
        //ref
        let state1 = ref(1);
        watch(
          state1,
          (count) =>{
            console.log(count); //2
          }
        )
    
        function fn1() {
          state1.value = 2;
        }
    
        return {
          state,
          fn,
          fn1,
          state1
        }
      }
    }
    </script>
    

    结语

    谢谢阅读,希望没有浪费您的时间。可以结合代码例子自己敲敲代码,响应性API还有很多用处,这里只介绍了九牛一毛。2021年到来,赶快行动起来吧!


    起源地下载网 » 「快速学习系列」我熬夜整理了Vue3.x响应性API

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元