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><liv-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><liv-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.pageXthis.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><liv-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.pageXthis.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.pageXy.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><liv-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.pageXy.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)