美文网首页熊爸的学习时间
跟技术胖学vue3.0(typescript版)(二) set

跟技术胖学vue3.0(typescript版)(二) set

作者: 熊爸天下_56c7 | 来源:发表于2020-10-14 22:12 被阅读0次

    tips: vue2.0 和 vue3.0的区别

    • 没有data methods computed 那些内容了 而是用setup()函数代替
    • <template>里的“根元素”不再只能是一个了

    一. setup() 函数

    现在, 我们没有必要把数据写在 data里 把方法写在methods 里了

    我们把数据和方法写在setup里, 再通过return 暴露出去

    <template>
      <h2>请选择服务员:</h2>
      <div>
        <button
          v-for="(name, index) in girls"
          v-bind:key="index"
          @click="selectGirlFun(index)"
        >
          {{ index }}:{{ name }}
        </button>
      </div>
      <h2>您选择了:{{ selectedGirl }}!!</h2>
    </template>
    
    <script lang="ts">
    import { defineComponent, ref } from "vue";
    
    export default defineComponent({
      name: "App",
      setup() {
        const girls = ref(["貂蝉", "王昭君", "西施", "杨玉环"]);
        const selectedGirl = ref("");
        const selectGirlFun = (index: number) => {
          selectedGirl.value = girls.value[index];
        };
        return {
          girls,
          selectedGirl,
          selectGirlFun,
        };
      },
    });
    </script>
    
    <style>
    #app {
      font-family: Avenir, Helvetica, Arial, sans-serif;
      -webkit-font-smoothing: antialiased;
      -moz-osx-font-smoothing: grayscale;
      text-align: center;
      color: #2c3e50;
      margin-top: 60px;
    }
    </style>
    

    二. ref() 函数

    我们看到, 上述例程中使用了 ref()函数
    ref()这个函数使得我们的变量拥有了双向绑定属性,
    这是和vue2.0中写在data里就可以双向绑定是不同的.

    下面我们通过一个错误的例程和 修改后正确的例程来说明此函数

    错误的例程

    实验结果也是错的, a其实在增加, 但并没有显示在页面上

    正确但例程, 要用到vue3.0 的 ref函数

    把程序改正确很简单

    1. 引入ref
    2. 给a赋值一个ref对象, 具体是ref(1)
    3. 现在a指向了一个ref对象, 所以声明a不是let了, 是const
    4. a的值要用 a.value来获取

    上面一直在说ref对象, 其实人家的真实类型是:RefImpl, 可以从下面的截图看出它的结构

    <template>
      <h2>{{ a }}</h2>
      <button @click="add">+</button>
    </template>
    
    <script lang="ts">
    import { defineComponent, ref } from "vue";
    
    export default defineComponent({
      name: "App",
      setup() {
        const a= ref(1);
        const add = () => {
          a.value += 1;
          console.log(a);
        };
        return {
          a,
          add
        };
      },
    });
    </script>
    
    <style>
    #app {
      font-family: Avenir, Helvetica, Arial, sans-serif;
      -webkit-font-smoothing: antialiased;
      -moz-osx-font-smoothing: grayscale;
      text-align: center;
      color: #2c3e50;
      margin-top: 60px;
    }
    </style>
    
    这样做有什么好处?

    这样做的好处是区分了需要界面显示的变量和只参与script内部运算的变量, 从而不做不必要的数据绑定, 提高性能.

    三. reactive()

    除了ref这种方式, 我们还有一种方式可以把数据设置成双向绑定数据, 那就是reactive()
    这也是和ref一样的把变量绑定到双向数据绑定对象的方法, 这个函数接收一个对象作为参数
    下面,我们尝试将上面那个a++的例子改为reactive

    <template>
      <h2>{{ a.value }}</h2>
      <button @click="add">+</button>
    </template>
    
    <script lang="ts">
    import { reactive } from "vue"; //从vue模组引入reactive函数 
    
    export default ({
      name: "App",
      setup() {
        const a= reactive({value:1}); //reactive接收对象作为参数, 所以应该这样写
        const add = () => {
          a.value += 1; //所以这里也要修改 a的value属性 上面也要显示a的value属性
          console.log(a);
        };
        return {
          a,
          add
        };
      },
    });
    </script>
    
    <style>
    #app {
      font-family: Avenir, Helvetica, Arial, sans-serif;
      -webkit-font-smoothing: antialiased;
      -moz-osx-font-smoothing: grayscale;
      text-align: center;
      color: #2c3e50;
      margin-top: 60px;
    }
    </style>
    

    根据控制台输出, 我们可以看到 a 现在是一个Proxy挂钩, 挂在一个target 对象上

    所以网上说的ref是reactive的一个特例是不对的, 虽然两者用法很相似

    四. reactive进阶用法----像vue2.0一样用vue3.0 😂😂😂

    我们以上文中的四大美女服务员为例:

    1. 进化第一步: 改造为reactive() 绑定数据
    <template>
      <h2>请选择服务员:</h2>
      <div>
        <button
          v-for="(name, index) in data.girls"
          v-bind:key="index"
          @click="data.selectGirlFun(index)"
        >
          {{ index }}:{{ name }}
        </button>
      </div>
      <h2>您选择了:{{ data.selectedGirl }}!!</h2>
    </template>
    
    <script lang="ts">
    import { reactive } from "vue";
    
    export default {
      name: "App",
      setup() {
        const data = reactive({
          girls: ["貂蝉", "王昭君", "西施", "杨玉环"],
          selectedGirl: "",
          selectGirlFun: (index: number) => {
            data.selectedGirl = data.girls[index];
          },
        });
        return {
          data,
        };
      },
    };
    </script>
    
    <style>
    #app {
      font-family: Avenir, Helvetica, Arial, sans-serif;
      -webkit-font-smoothing: antialiased;
      -moz-osx-font-smoothing: grayscale;
      text-align: center;
      color: #2c3e50;
      margin-top: 60px;
    }
    </style>
    
    1. 进化第二步: 既然使用了typescript, 将data的数据类型指定好
      这里采用typescript的接口思想
    1. 进化第三步: 每次都用data.xxx 太麻烦, 能不能用...扩展运算符省略掉data.?

    直接用扩展运算符是不行的 因为扩展运算符会取消data的响应式
    要使用 toRefs函数

    toRefs()接收一个reactive object,并把它变成一个ToRefs<T>的泛型类型,使其具有双向数据绑定的特性

    <template>
      <h2>请选择服务员:</h2>
      <div>
        <button
          v-for="(name, index) in girls"
          v-bind:key="index"
          @click="selectGirlFun(index)"
        >
          {{ index }}:{{ name }}
        </button>
      </div>
      <h2>您选择了:{{ selectedGirl }}!!</h2>
    </template>
    
    <script lang="ts">
    import { reactive,  toRefs } from "vue"; //从vue中引入 toRefs
    interface DataProp {
      girls: string[];
      selectedGirl: string;
      selectGirlFun: (index: number) => void;
    }
    export default {
      name: "App",
      setup() {
        const data: DataProp = reactive({
          girls: ["貂蝉", "王昭君", "西施", "杨玉环"],
          selectedGirl: "",
          selectGirlFun: (index: number) => {
            data.selectedGirl = data.girls[index];
          },
        });
        const refdata = toRefs(data); //把data转为ref类型对象
        console.log(data);
        console.log(refdata);
        return {
          ...refdata, //用扩展运算符扩展这个变量
        };
      },
    };
    </script>
    
    <style>
    #app {
      font-family: Avenir, Helvetica, Arial, sans-serif;
      -webkit-font-smoothing: antialiased;
      -moz-osx-font-smoothing: grayscale;
      text-align: center;
      color: #2c3e50;
      margin-top: 60px;
    }
    </style>
    

    toRefs 从控制台打印data 和 refdata 进行比较

    相关文章

      网友评论

        本文标题:跟技术胖学vue3.0(typescript版)(二) set

        本文链接:https://www.haomeiwen.com/subject/zwuepktx.html