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函数
把程序改正确很简单
- 引入ref
- 给a赋值一个ref对象, 具体是ref(1)
- 现在a指向了一个ref对象, 所以声明a不是let了, 是const
- 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 😂😂😂
我们以上文中的四大美女服务员为例:
- 进化第一步: 改造为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>
- 进化第二步: 既然使用了typescript, 将data的数据类型指定好
这里采用typescript的接口思想
- 进化第三步: 每次都用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 进行比较
网友评论