vue3-setup-基本使用-理解它的作用
摘要本文介绍了setup支持的组合式api的两个好处。内容•业务分离•组合业务分离下面是一段描述vue2代码的伪代码new Vue({data () {数据项1:[],数据项2:{}},methods: {与数据1相关的操作 () {}与数据2相关的操作 () {}},computed: {与数据1相关的计算属性:(){}与数据2相关的计算属性:(){}}})缺点:与数据1相关的代码分散在不同的配
摘要
本文介绍了setup支持的组合式api的两个好处。
内容
•业务分离•组合
业务分离
下面是一段描述vue2代码的伪代码
new Vue({
data () {
数据项1:[],
数据项2:{}
},
methods: {
与数据1相关的操作 () {}
与数据2相关的操作 () {}
},
computed: {
与数据1相关的计算属性:(){}
与数据2相关的计算属性:(){}
}
})
缺点:与数据1相关的代码分散在不同的配置项中,并没有集中起来,不方便写代码:你往往需在不同配置项中跳转。例如:添加一个数据要去data中,添加对应的操作方法要在methods中.....。
在vue3,我们可以这样写
const use数据项1 = function() {
const 数据项1 = reactive({})
const 计算属性1 = computed(()=>{})
const 操作1 = ()=>{}
return {数据项1, 计算属性1,操作1}
}
const use数据项2 = function() {
return {数据项2, 计算属性2,操作2}
}
new Vue({
data () {},
setup () {
const { 数据项1, 计算属性1,操作1 } = use数据项1()
const { 数据项2, 计算属性2,操作2 } = use数据项2()
return { 数据项1, 计算属性1,操作1 , 数据项2, 计算属性2,操作2}
}
})
它的典型特点是,可以把业务相关的代码在放在同一个位置来写。
用vue2写的todolist
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>html页面</title>
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
</head>
<body>
<div id="app">
<h2>vue2的todolist</h2>
<ul>
<li
v-for="item in list"
:key="item.id"
> <input type="checkbox" @click="hSwitchStatus(item)" :checked="item.isDone"/> {{item.content}}</li>
</ul>
<hr>
<div>
内容<input type="text" v-model="todo.content"> <br>
<input type="submit" @click.prevent="hAdd" value="添加">
</div>
</div>
<script>
const initData = [
{id:1, content: '下载vue3', isDone: true},
{id:2, content: '使用setup', isDone: false},
{id:3, content: '使用mock', isDone: false},
]
function mockData () {
return new Promise((resolve,reject) => {
setTimeout(() => {
resolve(initData)
}, 1000)
})
}
new Vue({
el: "#app",
data() {
return {
todo: {
content: ''
},
list: []
}
},
async mounted (){
this.list = await mockData()
console.log(this.list)
},
methods: {
hSwitchStatus (item) {
item.isDone = !item.isDone
},
hAdd() {
this.list.push({
id: !this.list.length ? 1: this.list[this.list.length-1].id+1,
content: this.todo.content,
isDone: false
})
}
}
})
</script>
</body>
</html>
用vue3写的todolist-改进版本
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>html页面</title>
<script src="https://unpkg.com/vue@next"></script>
</head>
<body>
<div id="app">
<h2>解决数据和业务逻辑分离的问题</h2>
<ul>
<li
v-for="item in list"
:key="item.id"
> <input type="checkbox" @click="hSwitchStatus(item)" :checked="item.isDone"/> {{item.content}}</li>
</ul>
<hr>
<div>
内容<input type="text" v-model="todo.content">
<input type="submit" @click.prevent="hAdd" value="添加">
</div>
</div>
<script>
const initData = [
{id:1, content: '学习vue3', isDone: true},
{id:2, content: '学习vue3', isDone: false},
{id:3, content: '学习vue3', isDone: false},
]
function mockData () {
return new Promise((resolve,reject) => {
setTimeout(() => {
resolve(initData)
}, 1000)
})
}
function useList () {
const list = Vue.ref([])
const hSwitchStatus = item => {
item.isDone = !item.isDone
}
const getData = async () => {
const rs = await mockData()
list.value = rs
}
return { list, getData, hSwitchStatus }
}
function useAdd (list) {
const todo = Vue.reactive({
content: ''
})
const hAdd = () => {
// const {content} = Vue.toRefs(todo)
list.value.push({
id: !list.value.length ? 1: list.value[list.value.length-1].id+1,
content: todo.content,
isDone: false
})
}
return { todo, hAdd }
}
const ToDoLIST = {
data() {
return {}
},
setup (){
const { getData, list, hSwitchStatus } = useList()
const { hAdd, todo } = useAdd(list)
Vue.onMounted(getData)
return {
list, todo, hAdd, hSwitchStatus
}
}
}
const vm = Vue.createApp(ToDoLIST).mount('#app')
console.log(vm)
</script>
</body>
</html>
逻辑复用
vue2中的写法
在vue2中逻辑复用可以采用mixins来实现。例如,定义如下mixins:
const mouseposition = {
data () {
return {
x: 0,
y: 0
}
},
methods: {
update(e) {
this.x = e.pageX
this.y = e.pageY
}
},
mounted () {
// 提取为函数
window.addEventListener('mousemove', this.update)
},
beforeDestoryed() {
window.removeEventListener('mousemove', this.update)
}
}
用来它实时获取鼠标的位置,并保存到数据项中。如果在当前的某个应用中也需要用到获取鼠标位置的功能,则可以直接通过mixins来混入。步骤分成两步:
1.引入mixins2.在视图(代码)中使用x,y
new Vue({
mixins: [mouseposition],
//..
})
示例:下面的例子完整演示了mixin的用法
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>html页面</title>
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
</head>
<body>
<div id="app">
<h2>mixin复用逻辑</h2>
{{x}}-{{y}}
<ul>
<li
v-for="item in list"
:key="item.id"
> <input type="checkbox" @click="hSwitchStatus(item)" :checked="item.isDone"/> {{item.content}}</li>
</ul>
<hr>
<div>
内容<input type="text" v-model="todo.content"> <br>
<input type="submit" @click.prevent="hAdd" value="添加">
</div>
</div>
<script>
const mouseposition = {
data () {
return {
x: 0,
y: 0
}
},
methods: {
update(e) {
this.x = e.pageX
this.y = e.pageY
}
},
mounted () {
window.addEventListener('mousemove', this.update)
},
beforeDestory() {
window.removeEventListener('mousemove', this.update)
}
}
const initData = [
{id:1, content: '下载vue3', isDone: true},
{id:2, content: '使用setup', isDone: false},
{id:3, content: '使用mock', isDone: false},
]
function mockData () {
return new Promise((resolve,reject) => {
setTimeout(() => {
resolve(initData)
}, 1000)
})
}
new Vue({
el: "#app",
mixins: [mouseposition], // 混入
data() {
return {
todo: {
content: ''
},
list: []
}
},
async mounted (){
this.list = await mockData()
console.log(this.list)
},
methods: {
hSwitchStatus (item) {
item.isDone = !item.isDone
},
hAdd() {
this.list.push({
id: !this.list.length ? 1: this.list[this.list.length-1].id+1,
content: this.todo.content,
isDone: false
})
}
}
})
</script>
</body>
</html>
上面的代码是可以工作的,但是有个非常不好的体验:mixins中的data会混入到当前组件中,但是由于并没有显式声明这个数据源,会导致在当前组件根本无法得知某个mixin到底混入了哪些数据。 下面来看,如果在vue3中应该如何解决。
const useMousePosition = function (){
const x = Vue.ref(0)
const y = Vue.ref(0)
// 提取为函数
function update(e) {
x.value = e.pageX
y.value = e.pageY
}
Vue.onMounted(() => {
window.addEventListener('mousemove', update)
})
Vue.onUnmounted(() => {
window.removeEventListener('mousemove', update)
})
return { x, y }
}
代码如下:
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>html页面</title>
<script src="https://unpkg.com/vue@next"></script>
</head>
<body>
<div id="app">
<h2>逻辑复用</h2>
{{x}}-{{y}}
<ul>
<li
v-for="item in list"
:key="item.id"
> <input type="checkbox" @click="hSwitchStatus(item)" :checked="item.isDone"/> {{item.content}}</li>
</ul>
<hr>
<div>
内容<input type="text" v-model="todo.content">
<input type="submit" @click.prevent="hAdd" value="添加">
</div>
</div>
<script>
const useMousePosition = function (){
const x = Vue.ref(0)
const y = Vue.ref(0)
function update(e) {
x.value = e.pageX
y.value = e.pageY
}
Vue.onMounted(() => {
window.addEventListener('mousemove', update)
})
Vue.onUnmounted(() => {
window.removeEventListener('mousemove', update)
})
return { x, y }
}
const initData = [
{id:1, content: '学习vue3', isDone: true},
{id:2, content: '学习vue3', isDone: false},
{id:3, content: '学习vue3', isDone: false},
]
function mockData () {
return new Promise((resolve,reject) => {
setTimeout(() => {
resolve(initData)
}, 1000)
})
}
function useList () {
const list = Vue.ref([])
const hSwitchStatus = item => {
item.isDone = !item.isDone
}
const getData = async () => {
const rs = await mockData()
list.value = rs
}
return { list, getData, hSwitchStatus }
}
function useAdd (list) {
const todo = Vue.reactive({
content: ''
})
const hAdd = () => {
// const {content} = Vue.toRefs(todo)
list.value.push({
id: !list.value.length ? 1: list.value[list.value.length-1].id+1,
content: todo.content,
isDone: false
})
}
return { todo, hAdd }
}
const ToDoLIST = {
data() {
return {}
},
setup (){
const { getData, list, hSwitchStatus } = useList()
const { hAdd, todo } = useAdd(list)
// 混入
const { x, y } = useMousePosition()
Vue.onMounted(getData)
return {
list, todo, hAdd, hSwitchStatus, x,y
}
}
}
const vm = Vue.createApp(ToDoLIST).mount('#app')
console.log(vm)
</script>
</body>
</html>
小结
setup是组合式api的入口,相比vue2它可以可以将不同的业务分离,并有更好的逻辑复用的体验。确实值得拥有。
更多推荐
所有评论(0)