setup函数
created示例被完全初始化之前执行
const app = Vue.createApp({
template:`
<div @click="handleClick">{{name}}</div>
`,
methods:{
test(){
console.log(this.$options.setup());
}
},
mounted() {
this.test();
},
//created示例被完全初始化之前
setup(props,context) {
return{
name:'dell',
handleClick:() => {
alert(1234);
}
}
}
});
ref和reactive响应式引用
1.通过proxy对数据进行封装,当数据变化时,触发模板等内容的更新
- ref处理基础类型的数据,reactive处理非基础型的数据
(1)ref:proxy,'dell'变成proxy({value:'dell'})这样的一个响应式引用
(2)reactive:proxy,{name:'dell'}变成proxy({name:'dell'})这样的一个响应式引用
const app = Vue.createApp({
template:`
<div>{{nameObj[0]}}</div>
`,
setup(props,context) {
// const{ ref }=Vue;
// //proxy,'dell'变成proxy({value:'dell'})这样的一个响应式引用
// let name=ref('dell');
// setTimeout(() => {
// name.value='lee'
// }, 2000);
// return{name}
const{ reactive}=Vue;
//proxy,{name:'dell'}变成proxy({name:'dell'})这样的一个响应式引用
let nameObj = reactive([123]);
setTimeout(() => {
nameObj[0]=456
}, 2000);
return{ nameObj }
}
});
(3)readonly只读,返回的对象不可被响应式修改
const{ reactive,readonly}=Vue;
const CopyNameObj = readonly(nameObj)
(4)toRefs
const app = Vue.createApp({
template:`
<div>{{name}},{{age}}</div>
`,
setup(props,context) {
const{ reactive,readonly,toRefs}=Vue;
nameObj.name='lee'
}, 2000);
const {name,age} =toRefs(nameObj);
return{ name,age }
}
});
toRef
const app = Vue.createApp({
template:`
<div>{{age}}</div>
`,
setup(props,context) {
const{ reactive,toRef}=Vue;
const data= reactive({name:'dell'});
const age = toRef(data,'age');
setTimeout(()=>{
age.value=55;
},2000);
return{ age }
}
});
context
const {attrs,slots,emit} = context;
(1)attrs是组件传递来的None-Props属性
(2)slots为父组件传递来的插槽
(3)emit向外触发一个事件
const app = Vue.createApp({
methods: {
handleChange(){
alert('change')
}
},
template:`
<child app='app' @change="handleChange">parent</child>
`,
});
app.component('child',{
template:`
<div @click="handleClick">123456</div>
`,
mounted() {
this.$emit('change');
},
// template:`
// <div>child</div>
// `,
setup(props,context) {
const { h } = Vue;
//slots为父组件传递来的插槽
//想外触发一个事件
const {attrs,slots,emit} = context;
//console.log(attrs.app);//attrs是组件传递来的None-Props属性
//console.log(slots.default());
//render函数h(标签,标签的属性,标签上的内容)
// return ()=> h('div',{},slots.default());
function handleClick(){
emit('change');
};
return{
handleClick
}
}
})
使用CompositionAPI开发todolist
关于list的操作进行封装
const listRelativeEffect = ()=>{
const { reactive }=Vue;
const list = reactive([]);
const addItemToList = (item)=>{
list.push(item);
};
return{ list, addItemToList }
};
关于inputValue的操作进行封装
const inputRelativeEffect = ()=>{
const { ref }=Vue;
const inputValue=ref('123');
const handleInputValueChange = (e)=>{
inputValue.value=e.target.value;
};
return{ inputValue,handleInputValueChange }
};
流程调度中转
const { list, addItemToList } = listRelativeEffect();
const { inputValue,handleInputValueChange } = inputRelativeEffect();
完整代码
<script>
//关于list的操作进行封装
const listRelativeEffect = ()=>{
const { reactive }=Vue;
const list = reactive([]);
const addItemToList = (item)=>{
list.push(item);
};
return{ list, addItemToList }
};
//关于inputValue的操作进行封装
const inputRelativeEffect = ()=>{
const { ref }=Vue;
const inputValue=ref('123');
const handleInputValueChange = (e)=>{
inputValue.value=e.target.value;
};
return{ inputValue,handleInputValueChange }
};
const app = Vue.createApp({
setup(props) {
//const {ref,reactive}=Vue;
//const inputValue=ref('123');
//const list = reactive([]);
// const handleInputValueChange = (e)=>{
// //console.log(e.target.value);
// inputValue.value=e.target.value;
// };
// const handleSubmit = ()=>{
// list.push(inputValue.value);
// };
//流程调度中转
const { list, addItemToList } = listRelativeEffect();
const { inputValue,handleInputValueChange } = inputRelativeEffect();
return{
list, addItemToList,
inputValue,handleInputValueChange,
}
},
template:`
<div>
<div>
<input :value="inputValue" @input="handleInputValueChange" />
<div>{{inputValue}}</div>
<button @click="()=>addItemToList(inputValue)">提交</button>
</div>
<ul>
<li v-for="(item,index) in list" :key="index">{{item}}</li>
</ul>
</div>
`,
});
const vm = app.mount("#root");
</script>
computed计算属性
使用:
const { reactive,computed } = Vue;
const app = Vue.createApp({
setup(props) {
const { reactive,computed } = Vue;
const countObj = reactive({count:0});
const handleClick = ()=>{
countObj.count+=1;
};
// const countAddFive = computed(()=>{
// //return count.value+5;
// });
const countAddFive = computed({
get:()=>{
return countObj.count+5;
},
set:(param)=>{
// return count.value=10;
countObj.count=param-5;
}
});
setTimeout(()=>{
countAddFive.value=100;
},3000);
return{
countObj,handleClick,countAddFive
}
},
template:`
<div>
<span @click="handleClick">{{countObj.count}}</span>----{{countAddFive}}
</div>
`,
});
watch和watchEffect的使用和差异性
1.watch侦听器
(1)具备一定的惰性
(2)参数可以拿到原始的和当前的值
(3)可以侦听多个数据的变化,用一个侦听器承载
watch(name,(currentValue,preventValue)=>{
console.log(currentValue,preventValue)
})
watch([()=>nameObj.name,()=>nameObj.EnglishName],([curName,curEng],[preName,preEng])=>{
console.log(curName,preName);
console.log(curEng,preEng);
});
(4)将watch变成非惰性{ immediate:true}
watch([()=>nameObj.name,()=>nameObj.EnglishName],([curName,curEng],[preName,preEng])=>{
console.log(curName,preName);
console.log(curEng,preEng);
},{ immediate:true});
2.watchEffect 侦听器,偏向于effect
(1)立即执行,没有惰性 immediate
(2)不需要传递你要侦听的内容,自动会感知代码依赖,不需要传递很多参数,只要转递一个回调函数
(3)不能获取之前数据的值
(4)异步操作放这里面合适些
watchEffect(()=>{
console.log('abc');
console.log(nameObj.name,nameObj.EnglishName);
})
定时取消监听
const stop = watchEffect(()=>{
console.log('abc');
console.log(nameObj.name,nameObj.EnglishName);
setTimeout(()=>{
stop();
},5000);
})
完整代码
const app = Vue.createApp({
setup(props) {
const { reactive, ref,watch,toRefs } = Vue;
const nameObj = reactive({name:'duck',EnglishName:'chicken'});
//const name = ref('dell');
// watch(name,(currentValue,preventValue)=>{
// console.log(currentValue,preventValue)
// })
// return{ name }
watch([()=>nameObj.name,()=>nameObj.EnglishName],([curName,curEng],[preName,preEng])=>{
console.log(curName,preName);
console.log(curEng,preEng);
});
const { name,EnglishName } = toRefs(nameObj);
return{ name,EnglishName }
},
template:`
<div>
<div>
Name:<input v-model="name" />
</div>
<div>
Name is {{name}}
</div>
<div>
EnglishName:<input v-model="EnglishName" />
</div>
<div>
EnglishName is {{EnglishName}}
</div>
</div>
`,
});
生命周期函数的新写法
beforeMount => onBeforeMount
mounted => onMounted
beforeUpdate => onBeforeUpdate
update =>onUpdate
beforeUnmount = >onBeforeUnmount 组件即将从页面移除时执行的方法
unmounted => onUnmounted 组件从页面中移除之后执行
onRenderTracked 每次渲染后重新收集响应式依赖
onRenderTriggered 每次触发页面重新渲染时执行
const app = Vue.createApp({
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 = "duck"
}
return{name,handleClick}
},
template:`
<div @click="handleClick">
{{name}}
</div>
`,
});
provide和inject
const app = Vue.createApp({
setup() {
const { ref ,provide, readonly} =Vue;
const name =ref('dell');
provide('name',readonly(name));
provide('changeName',(value)=>{
name.value=value
})
return{}
},
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>`
})
模板ref
CompositionAPI的情况下获取真实的DOM元素节点
固定写法ref(null)
const app = Vue.createApp({
setup() {
const {ref, onMounted } = Vue;
const hello = ref(null);//固定写法ref(null)
onMounted(() => {
console.log(hello.value);
});
return{hello}
},
//此处的ref为获取DOM节点的引用
template:`
<div ref="hello">
Hello World!
</div>
`,
});