论vue3.0和vue2.0区别之编程方式及例子详解

目录

前题

一、编程说明

二、vue3.0和vue2.0代码例子作比

三、扩展vue和react

四、vue3.0开发过渡笔记

版本

vue3的安装使用

生命周期的区别 

整体区别

总结


前题

首先了解一个新的功能首先要看它为什么出现,以及它的出现对现在的开发生态有哪些改变。

在vue2中我们进行开发叫做配置式开发 ,同一个功能逻辑可能需要 在data选项里写写,在methods里动动,生命周期再写两句,开发的时候可能不会觉得有什么。但是维护起来却有大问题。特别你要是对业务不熟悉接手别人的代码。

我一直都想着怎样能够面向功能块开发,将一个独立完整的业务功能封装成独立的代码块,这样既方便维护。同时封装相同的逻辑进行封装引用 ,也极大的降低了工作量,减少复制黏贴,以及复制黏贴过程中产生的错误。

vue3.0的变化可以总结为以下几点:

  • 更小
  • 更快
  • 加强typescript支持
  • Api一致性
  • 提高可维护能力
  • 开放更多底层功能
  • composition - 函数式编程1 首先,同样的业务不需要再在data和method中饱受分离之苦,业务块可以写在一起块,然后分离出去。2 其次,由于是函数,传参和返参方便多了。)
  • 生命周期
    • 新的option, 所有的组合API函数都在此使用, 只在初始化时执行一次
    • 函数如果返回对象, 对象中的属性或方法, 模板中可以直接使用
    • vue3中,生命周期是从vue中导出的,需要用到的要进行导入,setup除外
    • 除setup外,其他的生命周期都是写在setup中
    • setup函数是发生在beforeCreate之前的
  • Vue3打包
    打包使用可视化面板打包就可以但是打包后的dist文件不可以直接启动
    如果你想在本地运行的话需要使用phpstudy配置一下才可以打开
    然后要记住vue3打包后接口没有数据的情况那可能是网卡了等一会就好了

一、编程说明

vue2.0采用面向对象编程的思想,vue3.0则采用函数式编程的思想。

详细介绍:

面向对象编程

什么是对象

1、对象是单个事物的抽象,是一个具体的事物(一本书、一辆汽车、一个人都可以是对象,一个数据库、一张网页、一个与远程服务器的连接也可以是对象。当实物被抽象成对象,实物之间的关系就变成了对象之间的关系,从而就可以模拟现实情况,针对对象进行编程)。

2、对象是一个容器,封装了属性(property;属性是对象的状态特征)和方法(method;方法是对象的行为。例:完成了)。

3、在实际开发中,对象是一个抽象的概念,可以将其简单理解为:数据集或功能集。

4、ECMAScript-262 把对象定义为:无序属性的集合,其属性可以包含基本值、对象或者函数。

5、严格来讲,这就相当于说对象是一组没有特定顺序的值。对象的每个属性或方法都有一个名字,而每个名字都映射到一个值。

面向对象的特征

  • 封装性(就是包装,把一些重用的内容进行包装,在需要的时候,直接使用把一个值,存放在一个变量中,把一些重用的代码放在函数中,把好多相同功能的函数放在一个对象中,把好多功能的对象,放在一个文件中,把一些相同的内容放在一个对象中)
  • 继承性(类与类之间的关系,js中没有类的概念,js中有构造函数的概念,是可以有继承的,是基于原型)
  • 多态性(同一个行为,针对不同的对象,产生了不同的效果)

编程思想:
面向对象:提出需求,找对象,对象解决,注重的是结果 

原型prototype

构造函数、实例、原型三者之间的关系

论vue3.0和vue2.0区别之编程方式及例子详解_第1张图片

函数式编程

1、vue3 英文版说明

vue3 API相关的RFC,地址:https://github.com/vuejs/rfcs/blob/function-apis/active-rfcs/0000-function-api.md

2、函数式编程是一种编程范式,主要是利用函数把运算过程封装起来,通过组合各种函数来计算结果。

例子,假设我们要把字符串 functional programming is great 变成每个单词首字母大写,我们可以这样实现:

var string = 'functional programming is great';
var result = string
  .split(' ')
  .map(v => v.slice(0, 1).toUpperCase() + v.slice(1))
  .join(' ');

上面的例子先用 split 把字符串转换数组,然后再通过 map 把各元素的首字母转换成大写,最后通过 join 把数组转换成字符串。 整个过程就是 join(map(split(str))),体现了函数式编程的核心思想: 通过函数对数据进行转换。
由此我们可以得到,函数式编程有两个基本特点:
• 通过函数来对数据进行转换
• 通过串联多个函数来求结果

3、对比声明式与命令式(见二中e3.0例子容易理解)

  •  命令式:我们通过编写一条又一条指令去让计算机执行一些动作,这其中一般都会涉及到很多繁杂的细节。命令式代码中频繁使用语句,来完成某个行为。比如 for、if、switch、throw 等这些语句。
  • 声明式:我们通过写表达式的方式来声明我们想干什么,而不是通过一步一步的指示。表达式通常是某些函数调用的复合、一些值和操作符,用来计算出结果值。
//命令式
var CEOs = [];
//----------for(var i = 0; i < companies.length; i++){
for(var i in companies){
  CEOs.push(companies[i].CEO)
}

//声明式
var CEOs = companies.map(c => c.CEO);

 4、函数式编程常见特性

无副作用,指调用函数时不会修改外部状态,即一个函数调用 n 次后依然返回同样的结果。

var a = 1;
// 含有副作用,它修改了外部变量 a
// 多次调用结果不一样
function test1() {
  a++
  return a;
}

// 无副作用,没有修改外部状态
// 多次调用结果一样
function test2(a) {
  return a + 1;
}
透明引用
指一个函数只会用到传递给它的变量以及自己内部创建的变量,不会使用到其他变量。
var a = 1;
var b = 2;
// 函数内部使用的变量并不属于它的作用域
function test1() {
  return a + b;
}
// 函数内部使用的变量是显式传递进去的
function test2(a, b) {
  return a + b;
}

 不可变变量
指的是一个变量一旦创建后,就不能再进行修改,任何修改都会生成一个新的变量。使用不可变变量最大的好处是线程安全。多个线程可以同时访问同一个不可变变量,让并行变得更容易实现。 由于 JavaScript 原生不支持不可变变量,需要通过第三方库来实现。 (如 Immutable.js,Mori 等等)

var obj = Immutable({ a: 1 });
var obj2 = obj.set('a', 2);
console.log(obj);  // Immutable({ a: 1 })
console.log(obj2); // Immutable({ a: 2 })


函数是一等公民
我们常说函数是JavaScript的"第一等公民",指的是函数与其他数据类型一样,处于平等地位,可以赋值给其他变量,也可以作为参数,传入另一个函数,或者作为别的函数的返回值。下文将要介绍的闭包、高阶函数、函数柯里化和函数组合都是围绕这一特性的应用

5、常见的函数式编程模型

1.闭包(Closure)

2.高阶函数

map
map() 方法创建一个新数组,其结果是该数组中的每个元素都调用一个提供的函数后返回的结果。map 不会改变原数组。
假设我们有一个包含名称和种类属性的对象数组,我们想要这个数组中所有名称属性放在一个新数组中

// 使用高阶函数
var animals = [
  { name: "Fluffykins", species: "rabbit" },
  { name: "Caro", species: "dog" },
  { name: "Hamilton", species: "dog" },
  { name: "Harold", species: "fish" },
  { name: "Ursula", species: "cat" },
  { name: "Jimmy", species: "fish" }
];
var names = animals.map(x=>x.name);
console.log(names); //["Fluffykins", "Caro", "Hamilton", "Harold", "Ursula", "Jimmy"]

filter
filter() 方法会创建一个新数组,其中包含所有通过回调函数测试的元素。filter 为数组中的每个元素调用一次 callback 函数, callback 函数返回 true 表示该元素通过测试,保留该元素,false 则不保留。filter 不会改变原数组,它返回过滤后的新数组。
假设我们有一个包含名称和种类属性的对象数组。 我们想要创建一个只包含狗(species: “dog”)的数组。

// 使用高阶函数
var animals = [
  { name: "Fluffykins", species: "rabbit" },
  { name: "Caro", species: "dog" },
  { name: "Hamilton", species: "dog" },
  { name: "Harold", species: "fish" },
  { name: "Ursula", species: "cat" },
  { name: "Jimmy", species: "fish" }
];
var dogs = animals.filter(x => x.species === "dog");
console.log(dogs); // {name: "Caro", species: "dog"}
// { name: "Hamilton", species: "dog" }

 reduce
reduce 方法对调用数组的每个元素执行回调函数,最后生成一个单一的值并返回。 reduce 方法接受两个参数:1)reducer 函数(回调),2)一个可选的 initialValue。
假设我们要对一个数组的求和:

// 不使用高阶函数
const arr = [5, 7, 1, 8, 4];
let sum = 0;
for (let i = 0; i < arr.length; i++) {
  sum = sum + arr[i];
}
console.log(sum);//25
// 使用高阶函数
const arr = [5, 7, 1, 8, 4];
const sum = arr.reduce((accumulator, currentValue) => accumulator + currentValue,0);
console.log(sum)//25

 函数组合 (Composition)
函数式编程的一个特点是通过串联函数来求值。然而,随着串联函数数量的增多,代码的可读性就会不断下降。函数组合来解决这个问题。
假设有一个 compose 函数,它可以接受多个函数作为参数,然后返回一个新的函数。当我们为这个新函数传递参数时,该参数就会「流」过其中的函数,最后返回结果。

//两个函数的组合
var compose = function(f, g) {
    return function(x) {
        return f(g(x));
    };
};

//或者
var compose = (f, g) => (x => f(g(x)));
var add1 = x => x + 1;
var mul5 = x => x * 5;
compose(mul5, add1)(2);// =>15 

二、vue3.0和vue2.0代码例子作比

vue3 -- DEMO




转换为vue2 -- DEMO




1、

对比一下,我们不难发现:
vue2是将mounted,data,computed,watch之类的方法作为一个对象的属性进行导出。
vue3新增了一个名为setup的入口函数,value, computed, watch, onMounted等方法都需要从外部import。

函数式编程为组件的编写提供了更高的灵活度与可读性,并且更符合一个前端编写者的习惯(或者叫做“编程直觉”)。

2、

在vue2中,watch、computed、data、method等API都是直接作为对象的属性,传给vue实例的。这意味着,我们开发者在开发时,脑中需要给这个对象的不同属性(data、method、mounted之类的)建立联系。但一旦代码规模变大,这种联系就非常吃力了,这集中表现在大型vue组件代码的可读性很低。我想,每个维护过1000+行vue组件的开发者都会有所体会

而在vue3中,我们可以像写一个方法一样去写这个组件的JS逻辑部分,使用import来按需引入。这样的好处显而易见,首先就是我们需要写的代码量少了,其次就是我们可以封装更多的子函数引用更多的公共函数去维护我们的代码,第三就是代码的可读性变高了。(当然,我们的打包体积也会变小)----  此处需要调研

调研笔记1: 

论vue3.0和vue2.0区别之编程方式及例子详解_第2张图片

论vue3.0和vue2.0区别之编程方式及例子详解_第3张图片 论vue3.0和vue2.0区别之编程方式及例子详解_第4张图片 

 

 调研笔记2: async函数、await关键字

  • async函数是使用async关键字声明的函数。 async函数是AsyncFunction构造函数的实例, 并且其中允许使用await关键字。asyncawait关键字让我们可以用一种更简洁的方式写出基于Promise的异步行为,而无需刻意地链式调用promise
//name 函数名称。
//param 要传递给函数的参数的名称。

async function name([param[, param[, ... param]]]) {
    statements //包含函数主体的表达式。可以使用await机制。
}
  • async/await的目的为了简化使用基于promise的API时所需的语法。async/await的行为就好像搭配使用了生成器和promise。
  • async函数可能包含0个或者多个await表达式。await表达式会暂停整个async函数的执行进程并出让其控制权,只有当其等待的基于promise的异步操作被兑现或被拒绝之后才会恢复进程。promise的解决值会被当作该await表达式的返回值。使用async / await关键字就可以在异步代码中使用普通的try / catch代码块。
  • await关键字只在async函数内有效。 
  • async函数一定会返回一个promise对象。如果一个async函数的返回值看起来不是promise,那么它将会被隐式地包装在一个promise中。例如,如下代码:
async function foo() {
   return 1
}
等价于:

function foo() {
   return Promise.resolve(1)
}

 调研文章

vue中使用async和await来实现同步和异步_aaron9185的博客-CSDN博客_async await vue

 调研笔记3: Promise

Promise 对象用于表示一个异步操作的最终完成 (或失败)及其结果值。

一个Promise,这个promise要么会通过一个由async函数返回的值被解决,要么会通过一个从async函数中抛出的(或其中没有被捕获到的)异常被拒绝。

三、扩展vue和react

vue和react最大的区别有两个,一是双向数据绑定 VS 单向数据流,二是模板语法 VS JSX

vue3.0在函数式编程方面,使其在一些API的使用、组件JS层的逻辑上更像react,但其仍为模板语法。

论vue3.0和vue2.0区别之编程方式及例子详解_第5张图片

四、vue3.0开发过渡笔记

版本

查看版本: npm view vue versions

npm i vue@lasted:下载的是vue2

  • vue2
  • vuex3
  • vue-router3
  • element-ui 2
  • npm i vue@next:下载的是vue3

vue3

  • vuex4
  • vue-router4
  • element-plus 1
  • npm i vuex@next vue-router@next element-plus

vue3的安装使用

  • 一、安装vue3:npm i vue@next
  • 二、安装vue3版本的项目
  • 三、安装vue-router、vuex
  • 四、安装less@3、less-loader@7
  • 五、配置vue.config.js,与vue2相同

生命周期的区别 

论vue3.0和vue2.0区别之编程方式及例子详解_第6张图片

整体区别

  • 版本号不同
  • 引用的vuex/vue-router版本不同
  • vue3的APP.vue的《template》 中支持多个根节点

区别一:vue3中推崇使用函数式编程;各种创建实例,都调用函数来创建,我们从vue中解构出各种各样的函数来使用 

区别二:Performance [pəˈfɔːməns]

重写了虚拟DOM的实现(跳过静态节点,只处理动态节点)
update性能提高1.3~2倍
SSR速度提高了2~3倍


区别三:Tree shaking [ˈʃeɪkɪŋ]

可以将无用模块“剪辑”,仅打包需要的【webpack新版本的】

区别四 Fragment ['frægmənt]

不再限于模板中的单个根节点[文档碎片]

区别五 [ˈtelɪpɔːt] 以前称为 [ˈpɔːtl],译作传送门

可以把组件内部的部分内容挂载到除#app的容器中()

  
你好,世界

区别六 [səˈspens]

可在嵌套层级中等待嵌套的异步依赖项,嵌套一个异步组件,可以在获取到数据之前加载loading效果

父组件------------------

 

子组件--------------------------

 

区别七:TypeScript更好的TypeScript支持

区别八:vue3支持把组件中的某些内容以图形的方式绘制到canvas画布上(Custom Renderer API自定义渲染器API)Apache ECharts 

自定义渲染器API
用户可以尝试WebGL自定义渲染器

区别九:vue3使用的Composition API:(Composition API聚合API):vue2遵循options API,vue3遵循Composition API

options API:数据根据功能划分到data、methods、computed、watch区域(分散式API)

Composition API:vue3中所有的数据方法都放到了setup()方法中,全部组合到了一起,没有细分(聚合式API)

组合式API,替换原有的 Options [ˈɒpʃnz] API
根据逻辑相关性组织代码,提高可读性和可维护性
更好的重用逻辑代码(避免mixins混入时命名冲突的问题)
但是依然可以延用 Options [ˈɒpʃnz] API


区别十:vue3中的响应式数据

劫持,基于Proxy实现的;vue3中的响应式数据劫持,不再基于vue2的Object.defineProperty(),而是基于ES6内置的Proxy(不兼容IE)。

//vue3中的响应式
        //基于ES6中的Proxy来实现的,new Proxy返回obj的代理对象
        let proxObj = new Proxy(obj, {//对obj的第一层做劫持
            //target代理的对象,key值
            get(target, key) {
                return target[key]
            },
            set(target, key, value) {
                if (target[key === value]) return;
                target[key] = value;
                //控制视图重新渲染,操作代理对象时触发渲染
                console.log('rendering');
            }
        })

区别十一:获取页面数据组件


import { ref, onMounted } from 'vue';
import api from '@/config/api/jsonConfig.js'
import commonData from '@/config/general/commonData.js'
/* 
Fcn:请求表格数据接口名
autoRequest:是否需要挂载完成后自动加载数据
*/
export default (Fcn,autoRequest) => {
    // 表格绑定数据
    const tableData = ref([])
    // 表格页码数据
    const paginationOpt = ref({
        pageNumber: 1,
        pageSize: 20,
        totalRecords: 0
    })
    // 获取表格数据
    const getTableData = async (params) => {
        let d = await api[Fcn]({ params: { ...params, organizationUID: commonData.currentOrg.organizationUID } })
        if (!d) return

        tableData.value =d.data.pagination? d.data.records:d.data
        paginationOpt.value = d.data.pagination
    }
    // 翻页
    const handleSizeChange = (v) => {
        paginationOpt.value.pageSize = v
        getTableData(paginationOpt.value)
    }
    const handleCurrentChange = (v) => {
        paginationOpt.value.pageNumber = v
        getTableData(paginationOpt.value)
    }
    // 挂载完成请求数据
    onMounted(() => {
        if(autoRequest) getTableData()
    })
    return { tableData, paginationOpt, getTableData, handleSizeChange, handleCurrentChange }
}



论vue3.0和vue2.0区别之编程方式及例子详解_第7张图片

页面组件:只需要将方法名传入即可


export default defineComponent({
  setup() {
    return {
      ...useTable("examSourcegetList",true),
    };
  },
});

总结

1.function component 将会是接下来各大框架发展的一个方向,function天然对TS的友好也是一个重要的影响。
2.react hook的上手成本相对于vue会难一些,vue天生规避了一些react中比较难处理的地方。
3.hook一定是大前端的一个趋势。

4.目前的项目中前端中体现的函数式编程比较多,后端更多的还是OOP的思想。
5.在大型的偏向工程话的项目中,使用面向对象的方式方便拓展,更易编写。在项目中的比较小的一些组织模块可以使用函数式编程来提高效率。

参考文章:vue3 为什么要使用composition函数式编程_白马湖小龙王的博客-CSDN博客_vue3函数式编程

从函数式编程和面向对象的思考到Vue3的函数式编程_治愈云_q1942951600的博客-CSDN博客_vue3函数式编程

你可能感兴趣的:(JavaScript深入进阶,vue.js,javascript,前端,vue3.0,vue3)