一、
vue2 v-for优先级高于v-if
vue3 v-if优先级高于 v-for
二、
新增 setup 属性 非常好用!
新的 setup
选项在组件创建之前执行
在 setup
中你应该避免使用 this
,因为它不会找到组件实例。setup
的调用发生在 data
property、computed
property 或 methods
被解析之前,所以它们无法在 setup
中被获取。
生命响应式变量
import { ref } from 'vue'
通过import vue3里面ref属性来进行
官网的例子
// src/components/UserRepositories.vue `setup` function
import { fetchUserRepositories } from '@/api/repositories'
import { ref } from 'vue'
// 在我们的组件中
setup (props) {
const repositories = ref([])
const getUserRepositories = async () => {
repositories.value = await fetchUserRepositories(props.user)
}
return {
repositories,
getUserRepositories
}
}
setup的生命周期钩子
因为 setup
是围绕 beforeCreate
和 created
生命周期钩子运行的,所以不需要显式地定义它们。换句话说,在这些钩子中编写的任何代码都应该直接在 setup
函数中编写。
beforeCreate -> use setup() setup替代
created -> use setup() setup替代
//vue中引入使用
import { ref, onMounted,onBeforeMount } from 'vue'
beforeMount -> onBeforeMount
mounted -> onMounted
beforeUpdate -> onBeforeUpdate
updated -> onUpdated
beforeUnmount -> onBeforeUnmount
unmounted -> onUnmounted
errorCaptured -> onErrorCaptured
renderTracked -> onRenderTracked
renderTriggered -> onRenderTriggered
activated -> onActivated
deactivated -> onDeactivated
watch 组件变化 toRefs 改变ref属性
import { ref, watch } from 'vue' //引入
// 在我们组件中
setup (props) {
// 使用 `toRefs` 创建对 `props` 中的 `user` property 的响应式引用
//因为 props 是响应式的,你不能使用 ES6 解构,它会消除 prop 的响应性。
//如果需要解构 prop,可以在 setup 函数中使用 toRefs 函数来完成此操作:
const { user } = toRefs(props)
const repositories = ref([])
const getUserRepositories = async () => {
// 更新 `prop.user` 到 `user.value` 访问引用值
repositories.value = await fetchUserRepositories(user.value)
}
onMounted(getUserRepositories)
// 在 user prop 的响应式引用上设置一个侦听器
watch(user, getUserRepositories)
return {
repositories,
getUserRepositories
}
}
watch 监听 对象里面属性
const state = reactive({ count: 0 })
watch(
() => state.count,
(count, prevCount) => {
/* ... */
}
)
新增 watchEffect 在页面加载时就更新
新增 computed 在set up中使用
import { ref, computed } from 'vue'
set up 使用
将每一个功能模块分散到各个js中
// src/composables/useUserRepositories.js
import { fetchUserRepositories } from '@/api/repositories'
import { ref, onMounted, watch } from 'vue'
export default function useUserRepositories(user) {
const repositories = ref([])
const getUserRepositories = async () => {
repositories.value = await fetchUserRepositories(user.value)
}
onMounted(getUserRepositories)
watch(user, getUserRepositories)
return {
repositories,
getUserRepositories
}
}
// src/composables/useRepositoryNameSearch.js
import { ref, computed } from 'vue'
export default function useRepositoryNameSearch(repositories) {
const searchQuery = ref('')
const repositoriesMatchingSearchQuery = computed(() => {
return repositories.value.filter(repository => {
return repository.name.includes(searchQuery.value)
})
})
return {
searchQuery,
repositoriesMatchingSearchQuery
}
}
在setup中利用其在组建生成前的引用各个模块的功能模块js
可以增强代码的复用性,有效地 减少vue页面js的代码量 ,让逻辑更加清晰,该优点在越大的项目中越明相。
个人理解的话 就是在向mvc又进一步
// src/components/UserRepositories.vue
import { toRefs } from 'vue'
import useUserRepositories from '@/composables/useUserRepositories'
import useRepositoryNameSearch from '@/composables/useRepositoryNameSearch'
import useRepositoryFilters from '@/composables/useRepositoryFilters'
export default {
components: { RepositoriesFilters, RepositoriesSortBy, RepositoriesList },
props: {
user: {
type: String,
required: true
}
},
setup(props) {
const { user } = toRefs(props)
const { repositories, getUserRepositories } = useUserRepositories(user)
const {
searchQuery,
repositoriesMatchingSearchQuery
} = useRepositoryNameSearch(repositories)
const {
filters,
updateFilters,
filteredRepositories
} = useRepositoryFilters(repositoriesMatchingSearchQuery)
return {
// 因为我们并不关心未经过滤的仓库
// 我们可以在 `repositories` 名称下暴露过滤后的结果
repositories: filteredRepositories,
getUserRepositories,
searchQuery,
filters,
updateFilters
}
}
}
setup() 是有两个参数的 一个props 一个context(上下文)
传递给 setup
函数的第二个参数是 context
。context
是一个普通 JavaScript 对象,暴露了其它可能在 setup
中有用的值:
context 上下文中允许的
expose //在setup 返回render函数时 让外部函数 能获取到数据 expose({})
attrs
slots
emit
context 上下文中不允许的
data
computed
methods
refs
(模板 ref)
在组合式api中使用 Provide inject
import { provide } from 'vue'
import { inject } from 'vue'
响应性 属性 使用ref 对象或数组 使用reactive provide值
readonly 声明 值不能被后代的inject修改
如果要确保通过 provide
传递的数据不会被 inject 的组件更改,我们建议对提供者的 property 使用 readonly
。
自定义指令directive 的两个参数 (el,binding) binding.arg binding.value
<div id="dynamicexample">
<h3>Scroll down inside this section ↓</h3>
<p v-pin:[direction]="200">I am pinned onto the page at 200px to the left.</p>
</div>
const app = Vue.createApp({
data() {
return {
direction: 'right'
}
}
})
app.directive('pin', {
mounted(el, binding) {
el.style.position = 'fixed'
// binding.arg 是我们传递给指令的参数
const s = binding.arg || 'top'
el.style[s] = binding.value + 'px'
}
})
app.mount('#dynamic-arguments-example')
和非 prop 的 attribute 类似,当在组件中使用时,自定义指令总是会被应用在组件的根节点上。
和 attribute 不同,指令不会通过 v-bind="$attrs"
被传入另一个元素。
Teleport的使用 可直接把 dom传送到body中进行定位等操作
app.component('modal-button', {
template: `
<button @click="modalOpen = true">
Open full screen modal! (With teleport!)
</button>
<teleport to="body">
<div v-if="modalOpen" class="modal">
<div>
I'm a teleported modal!
(My parent is "body")
<button @click="modalOpen = false">
Close
</button>
</div>
</div>
</teleport>
`,
data() {
return {
modalOpen: false
}
}
})
globalProperties 这可以代替 Vue 2.x 的 Vue.prototype
扩展: 设置一个全局访问property
app.config.globalProperties.foo = 'bar'
app.component('child-component', {
mounted() {
console.log(this.foo) // 'bar'
}
})