一、安装脚手架
vue create 项目名
二、绑定原理
1.Vue2绑定原理
• 访问器属性+虚拟DOM树
2.访问器属性的问题
• 只能在首次创建new Vue()对象时初始就有的属性,添加监视(访问器属性)。今后动态添加进来的成员,就无法自动添加访问器属性,也就无法自动得到监视。
• 无法给索引数组的数字下标添加访问器属性
• 结果,在vue程序中后添加成员,或通过下标修改索引数组中的元素值,页面都不自动更新!
• 比如:
3.Vue3的绑定原理
• ES6的Proxy代理对象
– proxy在目标对象的外层搭建了一层拦截,外界对目标对象的所有操作,都必须通过这层拦截。
– 优点: 对象内部所有现有属性自动被监视,而且更可贵的是,后添加的属性,一进入对象就被监视!
– 缺点: 兼容性问题
• 如何使用:
三、脚手架的变化
1.main.ts中的变化(了解)
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
createApp(App).use(store).use(router).mount('#app’)
//代替了new Vue()
2.页面组件内的变化
• 好消息:<template>和<style>没有任何变化
<div><!--template里和vue2写法完全一样-->
<button @click="minus">-</button>
<span>{{n}}</span>
<button @click="add">+</button>
</div>
•<script>中,Vue3也支持vue2的写法,但会逐渐不支持。
• <script>中新写法:
– 1. 引入vue模块中提供的函数,用于创建组件对象和加工组件对
象中的内容. – import { defineComponent, ref } from 'vue’;
– defineComponent是vue3提供的专门创建组件对象的函数
– ref是vue3提供的一个函数,专门将任何东西包装为一个能被监
视的proxy对象。
– 2. 用defineComponent()函数创建一个组件对象,依然可以用
components成员引入其他子组件。(与vue2相同)
export default defineComponent({
name: 'Home’,
components: {
子组件对象, …
},
})
– 3. defineComponent({})函数内,必须先调用setup()函数作为
整个组件代码的运行起点。
export default defineComponent({
… …
//必须:
//代替了之前的create阶段
//作为整个组件的运行起点
setup(){
//组件所需的所有变量和函数都放在setup()函数内
}
})
– 4. “界面”中所需的所有变量和函数,只要直接声明在setup()
函数内即可
– 5. 所有要在”界面”上使用的变量或事件处理函数都要放在
return中返回才行!
• 因为有的成员需要抛出到界面,而有的成员不需要抛出到界面仅程序内
部使用!
• return就是分水岭!
setup(){
… …
return {
n, add, minus
} }
四、Composition API
1.ref与toRefs
• 问题: 如果一个组件对象中有多个变量值都要返回给界面使用,难道每个变量值都要分别调用ref(),然后在return中还要罗列每个变量值?
• 解决: 将多个变量放在一个对象中,集中保存,并用ref和toRefs配合,为每个变量添加监视
• 如何:
– 1. 将这个功能所有变量都集中保存在一个自定义对象data中,并在创建对象时,用ref()包裹{}及其内容。
– 原理: ref()会深度遍历对象中每个成员,甚至遍历成员的子成员。并且自动为各级成员及其子成员添加监视
– 比如
const data=ref({
n:0,
arr:["亮亮","然然","东东"] })
– 2. 再将data对象中的成员分别解构出来,单独使用。
– 问题: ref包裹的对象成员虽然在对象内部是被监视的,但是,一旦解构出来,就成了普通的变量,不再受监视。修改变量,无法自动更新界面了。
– 解决: 解构时,=右边的data对象必须用toRefs()包裹。
– 原理: toRefs()会自动为从data中解构出的每个成员再次调用ref(),使每个成员即使解构出来,也是受监视的。
– 但是,使用toRefs()函数前,也必须先在开头import中从vue中解构出来才能用
import { defineComponent, ref, toRefs } from 'vue';
let {n,arr}=toRefs(data.value);
– 3. 将操作变量的方法们,集中保存在一个普通的自定义对象methods中。在方法中操作步骤2解构出来的变量时,不用加this,但是必须用.value才能访问变量值
const methods={
add(){ n.value++; },
minus(){ n.value>0&&n.value--; },
change(i:number){
if(i<2){ arr.value[i]=“逝去了” }
else{ arr.value[i]="❀" } } }
– 4. 最后return时,只需要打散data和methods两个对象,再拼接为一个大的对象返回。
– 强调: return中解构data对象时,也必须用toRefs包裹,才能保证解构出来的data中的变量受监视,更新变量可自动更新界面。
return {
...toRefs(data.value), ...methods
}
2.watch
• Vue3中的watch是通过函数实现的。且一个组件中可以有多个watch()。
• 如何:
– 1. 必须先在开头import中解构出watch函数
– 2. 调用watch函数,监视变量:
import { defineComponent, … …, watch } from 'vue';
watch(kw,(newVal, oldVal)=>{
console.log(`kw变量变了,新值为${newVal}, 旧值为${oldVal}`)
search();
})
3.directive
• Vue3中2种自定义指令:
– 1. 全局自定义指令: main.ts中:
– 强调: vue3自定义指令中用mounted()函数代替了vue2中的inserted()函数。但是其他用法保持一致。
var app=createApp(App);
app.directive("my-focus",{
mounted(el){
el.focus();
}
})
app.use(store).use(router).mount('#app')
– 2. 局部自定义指令: .vue文件中: – 说明: 除了mounted()代替了inserted()之外,其余与vue2相同
export default defineComponent({
directives:{"my-focus":{
mounted(el){
el.focus();
} }
},
setup(){
… …
4.计算属性
• Vue3中计算属性也是通过专门的函数实现的
• 如何:
– 1. 还是要在开头的import中解构出computed函数
import { defineComponent, … …, computed } from ‘vue’;
– 2. 一定在包含所有方法的自定义methods对象中添加计算属性方法,才能在return时被解构出来,才能在界面上使用
const methods={
… …,
total:computed(()=>{
var r=0;
for(var p of cart.value){ r+=p.price*p.count }
return r;
}) }
组件最后return时 { …toRefs(data.value), …methods }
5.过滤器
• Vue3中已不再支持过滤器!
• 可用计算属性代替
6.注册全局组件
• main.ts中:
app.component('my-component-name', {
/* ... */
})