setup
原因:逻辑点分散对接手项目的人不友好
// src/components/UserRepositories.vue
export default {
components: { RepositoriesFilters, RepositoriesSortBy, RepositoriesList },
props: {
user: {
type: String,
required: true
}
},
data () {
return {
repositories: [], // 1
filters: { ... }, // 3
searchQuery: '' // 2
}
},
computed: {
filteredRepositories () { ... }, // 3
repositoriesMatchingSearchQuery () { ... }, // 2
},
watch: {
user: 'getUserRepositories' // 1
},
methods: {
getUserRepositories () {
// 使用 `this.user` 获取用户仓库
}, // 1
updateFilters () { ... }, // 3
},
mounted () {
this.getUserRepositories() // 1
}
}
方法(关注点拆分)
该组件有以下几个职责:(逻辑点在代码中分散)
1.从假定的外部 API 获取该用户名的仓库,并在更改时刷新仓库
2.使用 searchQuery 字符串搜索仓库
3.使用 filters 对象筛选searchQuery匹配仓库
可见代码中分布太散(理解太浪费时间)
1.有 getUserRepositories、repositories
useRepository(user) {
// 闭包searchQuery
return {
getUserRepositories,
repositories
}
}
2. searchQuery、repositoriesMatchingSearchQuery
useRepositoryNameSearch(repositories) {
// 闭包searchQuery
return {
searchQuery,
repositoriesMatchingSearchQuery
}
}
3. filteredRepositories、updateFilters 、filteredRepositories
useRepositoryFilters(repositoriesMatchingSearchQuery) {
// 闭包filters
return {
updateFilters ,filteredRepositories
}
}
总结抽象方法(欢迎修改)
useXXX(...params)(XXX多为data即使用对象、params为该方法依赖)
data: ref(基本数据类型) 、reactive(指向数据类型) xxx
methods: 封装在引用xxx的useXXX中
watch: 封装在被观察xxx的useXXX中
computed:封装在使用xxx的useXXX中
方法实践(LazyLoad)
import { inBrowser } from './util'
import Lazy from './lazy'
const LazyComponent = (lazy) => {
return {
props: {
tag: {
type: String,
default: 'div'
}
},
render (h) {
return h(this.tag, null, this.show ? this.$slots.default : null)
},
data () {
return {
el: null, // 1
state: { // 2
loaded: false
},
rect: {}, // 3
show: false // 5
}
},
mounted () {
this.el = this.$el
lazy.addLazyBox(this)
lazy.lazyLoadHandler()
},
beforeDestroy () {
lazy.removeComponent(this)
},
methods: {
getRect () {
this.rect = this.$el.getBoundingClientRect()
},
checkInView () {
this.getRect()
return inBrowser &&
(this.rect.top < window.innerHeight * lazy.options.preLoad && this.rect.bottom > 0) &&
(this.rect.left < window.innerWidth * lazy.options.preLoad && this.rect.right > 0)
},
load () {
this.show = true
this.state.loaded = true
this.$emit('show', this)
},
destroy () {
return this.$destroy
}
}
}
}
LazyComponent.install = function (Vue, options = {}) {
const LazyClass = Lazy(Vue)
const lazy = new LazyClass(options)
Vue.component('lazy-component', LazyComponent(lazy))
}
export default LazyComponent
调用load方法修改show,并更具show判断是否加展示$slot.default
find nodes which in viewport and trigger load // inview
init IntersectionObserver // isIntersecting