VUE2和VUE3区别对比一览


## Vue3总结
### 官方文档
* [Vue3](https://v3.cn.vuejs.org/api/options*data.html)
* [Vue2](https://vuejs.bootcss.com/api/)
### Vue3相对于Vue2的语法特性

#### 1.获取数据
* vue2
```javascript
export default {
    
    
  data() {
    
    
  	return {
    
    
      name: 'myName',
    }
  },
  mounted() {
    
    
  	console.log(this.name)
  } 
}
  • vue3
import {
    
    ref} from 'vue'
export default {
    
    
  setup() {
    
    
  	const name = ref('myName')
	  console.log(name.value)
    return {
    
    name}
  }
}
2.使用方法
  • vue2
export default {
    
    
  methods: {
    
    
    show() {
    
    
      console.log('show方法被调用')
    }
  },
  mounted() {
    
    
  	this.show()
  }
}
  • vue3
import {
    
    onMounted} from 'vue'
export default {
    
    
  setup() {
    
    
    function show() {
    
    
      console.log('show方法被调用')
    }
    onMounted(() => {
    
    
      show()
    })
    return {
    
    show}
  }
}
3.子组件向父组件通信
  • vue2
export default {
    
    
  methods: {
    
    
    change() {
    
    
      this.$emit('valueChange', 3)
    }
  },
}
  • vue3
import {
    
    onMounted} from 'vue'
export default {
    
    
  setup(props, context) {
    
    
    function change() {
    
    
      context.emit('valueChange', 3)
    }
  }
}
4.获取Vuex对象
  • vue2
export default {
    
    
  mounted() {
    
    
  	console.log(this.$store.state.name)
	  this.$store.commit('show')
  } 
}
  • vue3
import {
    
    onMounted} from 'vue'
import {
    
    useStore} from 'vuex'
export default {
    
    
  setup(props, context) {
    
    
  	const store = useStore()
    onMounted(() => {
    
    
      console.log(store.name)
      store.commit('show')
    })
  }
}
5.v-for里的ref
  • vue3
<template>
  // el当前元素,divs是存储每个元素的数组
  <div v-for="(item, index) in list" :ref="el => { divs[index] = el }">{
   
   { item }}</div>
</template>
<script>
import {onMounted, ref} from 'vue';
export default {
  setup() {
    const divs = ref([]);
    onMounted(() => {
      console.log(divs.value)
    });
    return {
      divs
    };
  },
};
</script>
6.Vue3支持碎片,就是说在组件可以拥有多个根节点
  • vue2
<template>
  <div class='form-element'>
    <h2>{
   
   { title }}</h2>
  </div>
</template>
  • vue3
<template>
  <div class='form-element'></div>
  <h2> {
   
   { title }}</h2>
</template>
7.Composition API
  • Vue2与Vue3 最大的区别 — Vue2使用选项类型API(Options API)对比Vue3合成型API(Composition API)
    • 旧的选项型API在代码里分割了不同的属性: data,computed属性,methods,等等。新的合成型API能让我们用方法(function)来分割,相比于旧的API使用属性来分组,这样代码会更加简便和整洁。
  • 建立数据 data - Vue2中会把数据放入data属性中,Vue3中需要使用一个新的setup()方法,此方法在组件初始化构造的时候触发
    • 从vue引入reactive
    • 使用reactive()方法来声名我们的数据为响应性数据
    • 使用setup()方法来返回我们的响应性数据,从而我们的template可以获取这些响应性数据
  • vue2
export default {
    
    
  props: {
    
    
    title: String
  },
  data () {
    
    
    return {
    
    
      username: '',
      password: ''
    }
  },
  methods: {
    
    
    login () {
    
    
      // 登陆方法
    }
  },
  components:{
    
    
    "buttonComponent":btnComponent
  },
  computed:{
    
    
	  lowerCaseUsername(){
    
    
	    return this.username.toLowerCase();     
	  }
  }
}
  • vue3
<template>
  <div>
    <h2> {
   
   { state.username }} </h2>
  </div>
</template>
<script>
import { reactive } from 'vue'
export default {
  props: {
    title: String
  },
  setup () {
    const state = reactive({ //数据
      username: '',
      password: '',
      lowerCaseUsername: computed(() => state.username.toLowerCase()) //计算属性
    })
     //方法
    const login = () => {
      // 登陆方法
    }
    return { 
      login,
      state
    }
  }
}
</script>
8.生命周期钩子 — Lifecyle Hooks
Vue2--------------vue3
beforeCreate  -> setup()
created       -> setup()
beforeMount   -> onBeforeMount
mounted       -> onMounted
beforeUpdate  -> onBeforeUpdate
updated       -> onUpdated
beforeDestroy -> onBeforeUnmount
destroyed     -> onUnmounted
activated     -> onActivated
deactivated   -> onDeactivated
9.父子组件传参
import {
    
     toRefs } from 'vue'
setup(props, {
     
      attrs, slots, emit }) {
    
    
	const {
    
     title } = toRefs(props)
	console.log(title.value)
  onMounted(() => {
    
    
    console.log('title: ' + props.title)
  })
}
10.vue3 Teleport瞬移组件
  • Teleport一般被翻译成瞬间移动组件,实际上是不好理解的.我把他理解成"独立组件"
  • 他可以那你写的组件挂载到任何你想挂载的DOM上,所以是很自由很独立的
  • 以一个例子来看:编写一个弹窗组件
<template>
  <teleport to="#modal">
    <div id="center" v-if="isOpen">
      <h2><slot>this is a modal</slot></h2>
      <button @click="buttonClick">Close</button>
    </div>
  </teleport>
</template>
<script>
export default {
  props: {
    isOpen: Boolean,
  },
  emits: {
    'close-modal': null
  },
  setup(props, context) {
    const buttonClick = () => {
      context.emit('close-modal')
    }
    return {
      buttonClick
    }
  }
}
</script>
<style>
  #center {
    width: 200px;
    height: 200px;
    border: 2px solid black;
    background: white;
    position: fixed;
    left: 50%;
    top: 50%;
    margin-left: -100px;
    margin-top: -100px;
  }
</style>
  • 在app.vue中使用的时候跟普通组件调用是一样的
<template>
  <div id="app">
    <button @click="openModal">Open Modal</button><br/>
    <modal :isOpen="modalIsOpen" @close-modal="onModalClose"> My Modal !!!!</modal>
  </div>
</template>
<script>
import Modal from './components/Modal.vue'
import{ref} from 'vue'
export default {
  name: 'App',
  components: {
    Modal
  },
  setup() {
    const modalIsOpen = ref(false)
    const openModal = () => {
      modalIsOpen.value = true
    }
    const onModalClose = () => {
      modalIsOpen.value = false
    }
    return {
      modalIsOpen,
      openModal,
      onModalClose
    }
  }
}
</script>
<style>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>
  • Teleport 可以把modal组件渲染到任意你想渲染的外部Dom上,不必嵌套在#app中,这样就可以互不干扰了,可以把Teleport看成一个传送门,把你的组件传送到任何地方
  • 使用的时候 to属性可以确定想要挂载的DOM节点下面
  • 在public文件夹下的index.html中增加一个节点,这样可以看到modal组件就是没有挂载在app下,不再受app组件的影响了
<body>
  <div id="app"></div>
  <div id="modal"></div>
</body>
11.vue2与vue3在标签或者组件中的ref="formRef"的dom元素的使用
  • vue2中直接使用this. r e f s . f o r m R e f 或者 t h i s . refs.formRef或者this. refs.formRef或者this.refs[‘formRef’]的方式就可以获取该组件或者dom的内容
  • vue3中由于setup函数中没有了this,那该如何使用呢?
<template>
  <div ref="mainContainer" ></div>
</template>
<script>
setup() {
  const mainContainer = ref(null)
  onMounted(()=>{console.log(mainContainer)})
  return {
    mainContainer,
  }
}
</script>
  • 由于setup函数创建时还没有VNode 所以想要使用该属性必须得在onMounted函数里面可以使用获取
    ###table—cloums中render函数渲染组件的写法:
import { resolveComponent } from 'vue'   // 需先引入 resolveComponent
cloums中写法render写法
{
          title: '操作',
          align: 'center',
          width: 100,
          fixed: 'right',
          key: 'couTypeCategoryName',
          render: (h, params) => {
            return h(resolveComponent('el-switch'), {
              modelValue: params.row.isShow,
              'active-value': 1,
              'inactive-value': 0,
              // 'onUpdate:modelValue': value => params.row.state = value
              onChange: (val) => {
                
              },
            })
          }
  },

一、在Table表格中渲染input、switch等 在 3.x v-model中,自定义组件相当于传递一个modelValue prop 并发出一个update:modelValue事件

render: (h, params) => {
  return h(resolveComponent('el-input'), {
    size: 'small',
    modelValue: params.row.comments,
    'onUpdate:modelValue': (value) => (params.row.comments = value),
  })
},

二、插槽

  <template #footer>
    <span class="dialog-footer">
      <el-button>取消</el-button>
      <el-button type="primary">确定</el-button>
    </span>
  </template>

三、filters

在vue3中被移除
###Fragment
vue2每个模版必须有一个根节点
vue3可以有多个根节点

<!--vue2-->
<template>
  <div>
    <span></span>
    <span></span>
  </div>
</template>
<!--vue3-->
<template>
  <span>hello</span>
  <span>world</span>
</template>

###v-if v-for 优先级
vue2 时 v-for 优先级高,所以v-for 和v-if一起会耗性能,增加了喝多不必要的判断
vue3 v-if比v-for有更高的优先级
###vVNode Prop
vue2和vue3的虚拟dom参数有所区别,vue3更加扁平化

<!--vue2-->
render: (h, params) => {
    
    
  let btnArr = [
    h(
      'Button',
      {
    
    
        props: {
    
    
          type: 'primary',
        },
        style: {
    
    
          marginLeft: '8px',
        },
        on: {
    
    
          click: () => {
    
    
            this.modalType = 'detail'
            this.viewType = 2
            this.item = params.row
            this.pageStatus = true
            this.pState = true
          },
        },
      },
      '查看详情'
    ),
  ]
  return h('div', btnArr)
},
<!--vue3-->
render:(h,params)=>{
    
    
    return  h(resolveComponent('el-input-number'), {
    
    
        type: 'number',
        size: 'large',
        modelValue:params.row.value,
        stepStrictly:true,
        controls:false,
        min:"1",
        'onUpdate:modelValue':(value) => {
    
     params.row.value = parseInt(value)},
        style: {
    
     width:'200px'},
    })
}

###ref和reactive 响应式的基础
接受一个参数,返回一个响应式数据
不同的是ref一般处理基础数据类型,reactive一般处理引用数据类型
使用 reactive,toRefs 保证 reactive 对象属性保持响应性

import { ref, computed, reactive, toRefs } from 'vue'

setup() {
  const DataProps  = reactive({
    count: 0,
    increase: () => { data.count++},
    double: computed(() => data.count * 2)
  })
  const refData = toRefs(data)
  return {
    ...refData
  }
}

###v-model
vue2只能绑定一个,vue3可以绑定多个

<!--父组件-->
<template>
  // v-model:modelValue简写为v-model
  // 可绑定多个v-model
  <child
    v-model="state.name"
    v-model:age="state.age"
  />
</template>

<script setup>
  import { reactive } from 'vue'
  // 引入子组件
  import child from './child.vue'

  const state = reactive({
    name: 'Jerry',
    age: 20
  })
</script>
子组件
<template>
  <span @click="changeInfo">我叫{
   
   { modelValue }},今年{
   
   { age }}岁</span>
</template>

<script setup>
// import { defineEmits, defineProps } from 'vue'
// defineEmits和defineProps在<script setup>中自动可用,无需导入
// 需在.eslintrc.js文件中【globals】下配置【defineEmits: true】、【defineProps: true】

defineProps({
  modelValue: String,
  age: Number
})

const emit = defineEmits(['update:modelValue', 'update:age'])
const changeInfo = () => {
  // 触发父组件值更新
  emit('update:modelValue', 'Tom')
  emit('update:age', 30)
}
</script>


###defineComponent函数,只是对setup函数进行封装,返回options的对象;
###父组件获取子组件的属性和方法

<!--父组件-->
<template>
  <child ref="comp"></child>
  <button @click="handlerClick">按钮</button>
</template>
<script setup>
import child from "./comp/expose.vue"
import { ref } from "vue"
const comp = ref(null)
const handlerClick = () => {
  console.log(comp.value.a) // 获取子组件对外暴露的属性
  comp.value.someMethod() // 调用子组件对外暴露的方法
}
</script>
<!--子组件-->

<template>

  <div>{
   
   {a}}</div>
  <button @click='someMethod'>按钮子</button>
</template>
<script setup>
import { ref } from 'vue'
let someMethod=()=>{
  console.log(666)
}

const a = 1
const b = ref(2)

defineExpose({
  a,
  b,
  someMethod
})
</script>




###其他
1.vue2 defineProperty只能监听某个属性,不能对全对象监听
2 vue3 Proxy 代理,可以检测到数组内部数据的变化
3.vue3 Teleport瞬移组件
4.Vue2 - 这里把数据放入data属性中
5.vue 3 Composition API
需要使用一个新的setup()方法,此方法在组件初始化构造的时候触发。
从vue引入reactive
使用reactive()方法来声名我们的数据为响应性数据
使用setup()方法来返回我们的响应性数据,从而我们的template可以获取这些响应性数据
vue3Composition API生命后期
setup() :开始创建组件之前,在beforeCreate和created之前执行。创建的是data和method
onBeforeMount() : 组件挂载到节点上之前执行的函数。
onMounted() : 组件挂载完成后执行的函数。
onBeforeUpdate(): 组件更新之前执行的函数。
onUpdated(): 组件更新完成之后执行的函数。
onBeforeUnmount(): 组件卸载之前执行的函数。
onUnmounted(): 组件卸载完成后执行的函数

猜你喜欢

转载自blog.csdn.net/weixin_44149821/article/details/136079033