生命周期函数的新写法
准备一个代码模板:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>lesson</title>
<script src="https://unpkg.com/vue@next"></script>
</head>
<body>
<div id="root"></div>
</body>
<script>
const app = Vue.createApp({
setup() {
return { }
},
template: `
<div>
Hello World!
</div>
`,
});
const vm = app.mount('#root');
</script>
</html>
各种勾子函数如下写:
<script>
const app = Vue.createApp({
// beforeMount =>(等价于) onBeforeMount
// mounted => onMounted
// beforeUpdate => onBeforeUpdate
// beforeUnmount => onBeforeUnmount
// unmouted => onUnmounted
setup() {
const {
ref, onBeforeMount, onMounted, onBeforeUpdate, onUpdated,
onRenderTracked, onRenderTriggered
} = Vue;
const name = ref('dell')
onBeforeMount(() => {
console.log('onBeforeMount')
})
onMounted(() => {
console.log('onMounted')
})
onBeforeUpdate(() => {
console.log('onBeforeUpdate')
})
onUpdated(() => {
console.log('onUpdated')
})
// 每次渲染后重新收集响应式依赖
onRenderTracked(() => {
console.log('onRenderTracked')
})
// 每次触发页面重新渲染时自动执行
onRenderTriggered(() => {
console.log('onRenderTriggered')
})
const handleClick = () => {
name.value = 'lee'
}
return { name, handleClick }
},
template: `
<div @click="handleClick">
{{name}}
</div>
`,
});
const vm = app.mount('#root');
</script>
Provide、Inject模板
-
provide 和 inject 主要为高阶插件/组件库提供用例。
-
常用的父子组件通信方式都是父组件绑定要传递给子组件的数据,子组件通过props属性接收,一旦组件层级变多时,采用这种方式一级一级传递值非常麻烦,而且代码可读性不高,不便后期维护。
-
vue提供了provide和inject帮助我们解决多层次嵌套嵌套通信问题。在provide中指定要传递给子孙组件的数据,子孙组件通过inject注入祖父组件传递过来的数据。
准备模板代码:
<script>
const app = Vue.createApp({
setup() {
},
template: `
<div>
<child/>
</div>
`,
});
app.component('child',{
template: `<div>child</div>`,}
);
const vm = app.mount('#root');
</script>
Composition API中有provide
方法:
<script>
const app = Vue.createApp({
setup() {
//父组件准备传递给子组件的数据
const {
provide
} = Vue;
provide('name', 'dell')
},
template: `
<div>
<child/>
</div>
`,
});
app.component('child', {
//子组件接收父组件的参数
setup() {
const {
inject
} = Vue;
//如果name没有传值的话,默认值为hello
const name = inject('name','hello');
return{name}
},
template: `<div>child</div>`,
});
const vm = app.mount('#root');
</script>
如果子组件想要去改变父组件中的provide中的参数的值:
思路:子组件不能改变父组件provide中的值,只能调用父组件中存在的方法,执行父组件的方法去修改provide中的值。
为了方便观察,我们将provide中的name
的值设置为ref包裹,方便绑定数据,修改后及时联动。
<script>
const app = Vue.createApp({
setup() {
//父组件准备传递给子组件的数据
const {
provide,
ref
} = Vue;
provide('name', ref('dell'))
},
template: `
<div>
<child/>
</div>
`,
});
app.component('child', {
//子组件接收父组件的参数
setup() {
const {
inject
} = Vue;
//如果name没有传值的话,默认值为hello
const name = inject('name', 'hello');
const handleClick=()=>{
name.value='lee';
}
return {
name,handleClick
}
},
template: `<div @click="handleClick">{{name}}</div>`,
});
const vm = app.mount('#root');
</script>
以上能够实现目的,但是父组件的内容在子组件修改不符合数据流的要求。尽量让父组件去修改值。推荐写法如下:
<script>
const app = Vue.createApp({
setup() {
//父组件准备传递给子组件的数据
const {
provide,
ref
} = Vue;
const name = ref('dell');
provide('name', name);
provide('changeName', (value) => {
name.value = value;
})
},
template: `
<div>
<child/>
</div>
`,
});
app.component('child', {
//子组件接收父组件的参数
setup() {
const {
inject
} = Vue;
//如果name没有传值的话,默认值为hello
const name = inject('name', 'hello');
const changeName = inject('changeName');
const handleClick = () => {
changeName('lee');
}
return {
name,
handleClick
}
},
template: `<div @click="handleClick">{{name}}</div>`,
});
const vm = app.mount('#root');
</script>
为了防止上面的不建议写法,可以通过readonly
修饰,来限制子组件的权限:
......
provide('name', name);
......
修改为:
......
provide('name', readonly(name));
......
ref的用法
CompositionAPI 的语法下,获取真实的 DOM 元素节点(声明和ref对应上,就能获取真实的 DOM 元素节点)
<script>
// CompositionAPI 的语法下,获取真实的 DOM 元素节点
const app = Vue.createApp({
setup() {
const {
ref,
onMounted
} = Vue;
const hello = ref(null);//这样声明,和ref对应上,就能获取真实的 DOM 元素节点
//生命周期函数
onMounted(() => {
console.log(hello.value);
//<div>hello world</div>
})
return {
hello
}
},
template: `
<div>
<div ref="hello">hello world</div>
</div>
`,
});
const vm = app.mount('#root');
</script>
网友评论