逻辑分离和复用

Vue 2.x 代码写法

<template>
      <div class="search">
            <form>
                  <input v-model="searchValue" type="text" />
                  <button @click="search"></button>
            </form>
      </div>
      <ul class="result">
            <li class="result__item" v-for="item in filterData" :key="item.id">
                  {{ item.name }}
            </li>
      </ul>
      <span v-if="loading">Loading</span>
</template>
<script>
export default {
      data() {
            searchValue: '',
            loading: true,
            searchResult: []
      },
      computed: {
            filterData() {
                  return searchResult.filter(i => i.id > 3)
            }
      },
      methods: {
            async search() {
                  this.loading = true
                  const { data } = await fetch('/search', body: this.searchValue.trim())
                  this.searchResult = data.toJSON()
                  this.loading = false
            }
      },
      mounted() {
            this.search()
      }
}
</script>

使用 Composition API 下工作的代码

明显变化:

  1. 组件从原本的选项配置变成了函数定义
  2. 组件也不需要使用 this 去指定当前组件执行的上下文
<template>
      <div class="search">
            <form>
                  <input v-model="state.searchValue" type="text" />
                  <button @click="search"></button>
            </form>
            <ul class="result">
                  <li class="result__item" v-for="item in filterData" :key="item.id">
                        {{ item.name }}
                  </li>
            </ul>
            <span v-if="state.loading">Loading</span>
      </div>
</template>
<script>
import { reactive, computed, onMounted, toRef } from '@vue/composition-api'

export default {
      setup() {
            // 初始化数据
            const state = reactive({
                  searchValue: '',
                  loading: true,
                  searchResult: []
            })
		
            const filterData = computed(() => state.searchResult.filter(i => i.id > 3))
		
            async function search() {
                  state.loading = true
                  const { data } = await fetch('/search', body: this.searchValue.trim())
                  state.searchResult = data.toJSON()
                  state.loading = false
            }
		
            onMounted(() => {
                  search()
            })
            return { ...toRef(state), filterData, search }
      }
}
</script>

逻辑分离和复用

<script>
import { reactive, computed, onMounted, toRef, ref } from '@vue/composition-api'
// 方法提取
function useSearch() {
      const searchValue = ref('')
      const searchResult = ref([])
      const loading = ref(true)
	
      async function search() {
            loading.value = true
            const { data } = await fetch('/search', body: searchValue.trim())
            searchResult.value = data.toJSON()
            loading.value = false
      }
	
      onMounted(() => search())
	
      return { searchValue, searchResult, loading, search }
}

// 提取计算属性
function useFilterSearchResult(searchResult) {
      const filterData = computed(() => searchResult.value.filter(I=》 i.id > 3))
      return { filterData }
}

export default {
      setup(props, context) {
            const search = useSearch()
            return { 
                  ...search, 
                  ...useFilterSearchResult(search.searchResult)
            }
      }
}
</script>

缺点 (数据无响应情况)

当state作为一个返回值参数的时候,它实际是作为一个值传递到了另外一个方法中,所以getter、setter将会丢失,数据无法响应。引用传递及值传递

function useMounsePosition(){
      const pos = reactive({
            x: 0,
            y: 0
      })
      onMount(() => {})
      return pos
}
# 数据响应丢失清空
export default {
      setup() {
            // 这里只取了 useMousePosition 返回值的引用值
            // 而值里面的 getter / setter 丢失
            const { x, y } = useMousePosition()
            // 响应丢失
            return { x, y }
		
            // 响应丢失
            return { ...useMousePosition() }
		
            // 可以工作
            return {
                  pos: useMousePosition()
            }
      }
}

解决方案一 使用 toRefs

function useMounsePosition(){
      const pos = reactive({
            x: 0,
            y: 0
      })
      onMount(() => {})
      return toRefs(pos)
}
export default {
      setup() {
            // 正确
            const { x, y } = useMousePosition()
            return { x, y }
	     
            // 正确
            return { ...useMousePosition() }
      }
}

解决方案二 使用 ref去初始数据

unction useMounsePosition(){
      const x = ref(0)
      const y = ref(0)
	
      onMount(() => {
            document.body.addeventListener("mousemove", (e) => {
                  x.value = e.x
		  y.value = e.y
            })
      })
      return { x, y }
}
export default {
      setup() {
            // 正确
            const { x, y } = useMousePosition()
            return { x, y }
	
            // 正确
            return { ...useMousePosition() }
      }
}
原文地址:https://www.cnblogs.com/yuxi2018/p/14160943.html