美文网首页熊爸的学习时间
跟技术胖学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