返回顶部
首页 > 资讯 > 前端开发 > VUE >如何从一个组件的实现来深刻理解JS中的继承
  • 890
分享到

如何从一个组件的实现来深刻理解JS中的继承

2024-04-02 19:04:59 890人浏览 独家记忆
摘要

今天就跟大家聊聊有关如何从一个组件的实现来深刻理解js中的继承,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。其实,无论是写什么语言的程序员,最终的目

今天就跟大家聊聊有关如何从一个组件的实现来深刻理解js中的继承,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。

其实,无论是写什么语言的程序员,最终的目的,都是把产品或代码封装到一起,提供接口,让使用者很舒适的实现功能。所以对于我来说,往往头疼的不是写代码,而是写注释和文档!如果接口很乱,肯定会头疼一整天。

javascript 最初是以 WEB 脚本语言面向大众的,尽管现在出了服务器端的 nodejs,但是单线程的性质还没有变。对于一个 Web  开发人员来说,能写一手漂亮的组件极为重要。GitHub 上那些开源且 stars 过百的 Web 项目或组件,可读性肯定非常好。

从一个例子来学习写组件

组件教程的参考来自于 gitHub 上,通俗易懂,链接。

要实现下面这个功能,对一个 input 输入框的内容进行验证,只有纯数字和字母的组合才是被接受的,其他都返回 failed:

如何从一个组件的实现来深刻理解JS中的继承

全局变量写法

这种写法完全没有约束,基本所有人都会,完全没啥技巧:

// html <input type="text" id="input"/> // javascript var input = document.getElementById("input"); function getValue(){   return input.value; } function render(){   var value = getValue();   if(!document.getElementById("show")){     var append = document.createElement('span');     append.setAttribute("id", "show");     input.parentnode.appendChild(append);   }   var show = document.getElementById("show");   if(/^[0-9a-zA-Z]+$/.exec(value)){     show.innerHTML = 'Pass!';   }else{     show.innerHTML = 'Failed!';   } } input.addEventListener('keyup', function(){   render(); });

缺点自然不用多说,变量没有任何隔离,严重污染全局变量,虽然可以达到目的,但极不推荐这种写法。

对象隔离作用域

鉴于以上写法的弊端,我们用对象来隔离变量和函数:

var obj = {   input: null,   // 初始化并提供入口调用方法   init: function(config){     this.input = document.getElementById(config.id);     this.bind();     //链式调用     return this;   },   // 绑定   bind: function(){     var self = this;     this.input.addEventListener('keyup', function(){       self.render();     });   },   getValue: function(){     return this.input.value;   },   render: function(){     var value = this.getValue();     if(!document.getElementById("show")){       var append = document.createElement('span');       append.setAttribute("id", "show");       input.parentNode.appendChild(append);     }     var show = document.getElementById("show");     if(/^[0-9a-zA-Z]+$/.exec(value)){       show.innerHTML = 'Pass!';     }else{       show.innerHTML = 'Failed!';     }   } } window.onload = function(){   obj.init({id: "input"}); }

相对于开放式的写法,上面的这个方法就比较清晰了。有初始化,有内部函数和变量,还提供入口调用方法。

新手能实现上面的方法已经很不错了,还记得当初做百度前端学院题目的时候,基本就是用对象了。

不过这种方法仍然有弊端。obj  对象中的方法都是公开的,并不是私有的,其他人写的代码可以随意更改这些内容。当多人协作或代码量很多时,又会产生一系列问题。

函数闭包的写法

var fun = (function(){   var _bind = function(obj){     obj.input.addEventListener('keyup', function(){       obj.render();     });   }   var _getValue = function(obj){     return obj.input.value;   }   var InputFun = function(config){};   InputFun.prototype.init = function(config){     this.input = document.getElementById(config.id);     _bind(this);     return this;   }   InputFun.prototype.render = function(){     var value = _getValue(this);     if(!document.getElementById("show")){       var append = document.createElement('span');       append.setAttribute("id", "show");       input.parentNode.appendChild(append);     }     var show = document.getElementById("show");     if(/^[0-9a-zA-Z]+$/.exec(value)){       show.innerHTML = 'Pass!';     }else{       show.innerHTML = 'Failed!';     }   }   return InputFun; })(); window.onload = function(){   new fun().init({id: 'input'}); }

函数闭包写法的好处都在自执行的闭包里,不会受到外面的影响,而且提供给外面的方法包括 init 和 render。比如我们可以像 Jquery  那样,稍微对其改造一下:

var $ = function(id){   // 这样子就不用每次都 new 了   return new fun().init({'id': id}); } window.onload = function(){   $('input'); }

还没有涉及到原型,只是简单的闭包。

基本上,这已经是一个合格的写法了。

面向对象

虽然上面的方法以及够好了,但是我们的目的,是为了使用面向对象。面向对象一直以来都是被认为***的编程方式,如果每个人的代码风格都相似,维护、查看起来就非常的方便。

但是,我想在介绍面向对象之前,先来回忆一下 JS 中的继承(实现我们放到***再说)。

入门级的面向对象

提到继承,我首先想到的就是用 new 来实现。还是以例子为主吧,人->学生->小学生,在 JS 中有原型链这么一说,__proto__ 和  prototype ,对于原型链就不过多阐述,如果不懂的可以自己去查阅一些资料。

在这里,我还是要说明一下 JS 中的 new 构造,比如 var student = new Person(name),实际上有三步操作:

var student = {}; student.__proto__ = Person.prototype; Person.call(student, name)

得到的 student 是一个对象,__proto__执行 Person 的 prototype,Person.call 相当于  constructor。

function Person(name){   this.name = name; } Person.prototype.Say = function(){   console.log(this.name + ' can say!'); } var ming = new Person("xiaoming"); console.log(ming.__proto__ == Person.prototype) //true new的第二步结果 console.log(ming.name) // 'xiaoming' new 的第三步结果 ming.Say() // 'xiaoming can say!' proto 向上追溯的结果

利用 __proto__ 属性的向上追溯,可以实现一个基于原型链的继承。

function Person(name){   this.name = name; } Person.prototype.Say = function(){   console.log(this.name + ' can say!'); } function Student(name){   Person.call(this, name); //Person 的属性赋值给 Student } Student.prototype = new Person(); //顺序不能反,要在最前面 Student.prototype.DoHomeWork = function(){   console.log(this.name + ' can do homework!'); } var ming = new Student("xiaoming"); ming.DoHomeWork(); //'xiaoming can do homework!' ming.Say(); //'xiaoming can say!'

大概刚认识原型链的时候,我也就只能写出这样的水平了,我之前的文章。

打开调试工具,看一下 ming 都有哪些东西:

ming   name: "xiaoming"   __proto__: Person     DoHomeWork: ()     name: undefined //注意这里多了一个 name 属性     __proto__: Object       Say: ()       constructor: Person(name)       __proto__: Object

当调用 ming.Say() 的时候,刚好 ming.__proto__.__proto__ 有这个属性,这就是链式调用的原理,一层一层向下寻找。

这就是最简单的继承了。

面向对象的进阶

来看一看刚才那种做法的弊端。

  1. 没有实现传统面向对象该有的 super 方法来调用父类方法,链式和 super 方法相比还是有一定缺陷的;

  2. 造成过多的原型属性(name),constructor 丢失(constructor 是一个非常重要的属性,MDN)。

因为链式是一层层向上寻找,知道找到为止,很明显 super 直接调用父类更具有优势。

// 多了原型属性 console.log(ming.__proto__) // {name: undefined}

为什么会多一个 name,原因是因为我们执行了 Student.prototype = new Person();,而 new 的第三步会执行一个  call 的函数,会使得 Student.prototype.name = undefined,恰好 ming.__proto__ 指向 Student 的  prototype,用了 new 是无法避免的。

// 少了 constructor  console.log(ming.constructor == Person) //true  console.log(ming.constructor == Student) // false

这也很奇怪,明明 ming 是继承与 Student,却返回 false,究其原因,Student.prototype 的 constructor  方法丢失,向上找到了Student.prototype.__proto__ 的 constructor 方法。

如何从一个组件的实现来深刻理解JS中的继承

再找原因,这句话导致了 Student.prototype 的 constructor 方法丢失:

Student.prototype = new Person();

在这句话之前打一个断点,曾经是有的,只是被替换掉了:

如何从一个组件的实现来深刻理解JS中的继承

找到了问题所在,现在来改进:

// fn 用来排除多余的属性(name) var fn = function(){}; fn.prototype = Person.prototype; Student.prototype = new fn(); // 重新添上 constructor 属性 Student.prototype.constructor = Student;

用上面的继承代码替换掉之前的 Student.prototype = new Person();

面向对象的封装

我们不能每一次写代码的时候都这样写这么多行来继承吧,所以,于情于理,还是来进行简单的包装:

function classInherit(subClass, parentClass){   var fn = function(){};   fn.prototype = parentClass.prototype;   subClass.prototype = new fn();   subClass.prototype.constructor = subClass; } classInherit(Student, Person);

哈哈,所谓的包装,就是重抄一下代码。

进一步完善面向对象

上面的问题只是简单的解决了多余属性和 constructor 丢失的问题,而 supper 问题仍然没有改进。

举个栗子,来看看 supper 的重要,每个人都会睡觉,sleep 函数是人的一个属性,学生分为小学生和大学生,小学生晚上 9 点睡觉,大学生 12  点睡觉,于是:

Person.prototype.Sleep = function(){   console.log('Sleep!'); } function E_Student(){}; //小学生 function C_Student(){}; //大学生 classInherit(E_Student, Person); classInherit(C_Student, Person); //重写 Sleep 方法 E_Student.prototype.Sleep = function(){   console.log('Sleep!');   console.log('Sleep at 9 clock'); } C_Student.prototype.Sleep = function(){   console.log('Sleep!');   console.log('Sleep at 12 clock'); }

对于 Sleep 方法,显得比较混乱,而我们想要通过 supper,直接调用父类的函数:

E_Student.prototype.Sleep = function(){   this._supper(); //supper 方法   console.log('Sleep at 9 clock'); } C_Student.prototype.Sleep = function(){   this._supper(); //supper 方法   console.log('Sleep at 12 clock'); }

不知道对 supper 的理解正不正确,总感觉怪怪的,欢迎指正!

来看下 JQuery 之父是如何 class 的面向对象,原文在这,源码如下。

 // Inspired by base2 and Prototype (function(){   // initializing 开关很巧妙的来实现调用原型而不构造,还有回掉   var initializing = false, fnTest = /xyz/.test(function(){xyz;}) ? /\b_super\b/ : /.*/;   // The base Class implementation (does nothing)   // 全局,this 指向 window,***的父类   this.Class = function(){};     // Create a new Class that inherits from this class   // 继承的入口   Class.extend = function(prop) {     //保留当前类,一般是父类的原型     var _super = this.prototype;         // Instantiate a base class (but only create the instance,     // don't run the init constructor)     //开关 用来使原型赋值时不调用真正的构成流程     initializing = true;     var prototype = new this();     initializing = false;         // Copy the properties over onto the new prototype     for (var name in prop) {       // Check if we're overwriting an existing function       //对函数判断,将属性套到子类上       prototype[name] = typeof prop[name] == "function" &&         typeof _super[name] == "function" && fnTest.test(prop[name]) ?         (function(name, fn){           //用闭包来存储           return function() {             var tmp = this._super;                         // Add a new ._super() method that is the same method             // but on the super-class             this._super = _super[name];                         // The method only need to be bound temporarily, so we             // remove it when we're done executing             //实现同名调用             var ret = fn.apply(this, arguments);               this._super = tmp;             return ret;           };         })(name, prop[name]) :         prop[name];     }         // 要返回的子类     function Class() {       // All construction is actually done in the init method       if ( !initializing && this.init )         this.init.apply(this, arguments);     }     //前面介绍过的,继承     Class.prototype = prototype;         Class.prototype.constructor = Class;       Class.extend = arguments.callee;         return Class;   }; })();

这个时候就可以很轻松的实现面向对象,使用如下:

var Person = Class.extend({   init: function(name){     this.name = name;   },   Say: function(name){     console.log(this.name + ' can Say!');   },   Sleep: function(){     console.log(this.name + ' can Sleep!');   } }); var Student = Person.extend({   init: function(name){     this._super('Student-' + name);   },   Sleep: function(){     this._super();     console.log('And sleep early!');   },   DoHomeWork: function(){     console.log(this.name + ' can do homework!');   } }); var p = new Person('Li'); p.Say(); //'Li can Say!' p.Sleep(); //'Li can Sleep!' var ming = new Student('xiaoming'); ming.Say(); //'Student-xiaoming can Say!' ming.Sleep();//'Student-xiaoming can Sleep!'             // 'And sleep early!' ming.DoHomeWork(); //'Student-xiaoming can do homework!'

除了 John Resig 的 supper 方法,很多人都做了尝试,不过我觉得 John Resig 的实现方式非常的妙,也比较贴近 supper  方法,我本人也用源码调试了好几个小时,才勉强能理解。John Resig 的头脑真是令人佩服。

ES6 中的 class

在 JS 中,class 从一开始就属于关键字,在 es6 终于可以使用 class 来定义类。比如:

class Point {   constructor(x, y){     this.x = x;     this.y = y;   }   toString(){     return '(' + this.x + ',' + this.y + ')';   } } var p = new Point(3, 4); console.log(p.toString()); //'(3,4)'

更多有关于 ES6 中类的使用请参考阮一峰老师的 Class基本语法。

其实 ES6 中的 class 只是写对象原型的时候更方便,更像面向对象,class 的功能 ES5 完全可以做到,比如就上面的例子:

typeof Point; //'function' Point.prototype; 

和用 ES5 实现的真的没有什么差别,反而现在流行的一些库比 ES6 的 class 能带来更好的效益。

回到最开始的组件问题

那么,说了这么多面向对象,现在回到最开始的那个组件的实现&mdash;&mdash;如何用面向对象来实现。

还是利用 John Resig 构造 class 的方法:

var JudgeInput = Class.extend({   init: function(config){     this.input = document.getElementById(config.id);     this._bind();   },   _getValue: function(){     return this.input.value;   },   _render: function(){     var value = this._getValue();     if(!document.getElementById("show")){       var append = document.createElement('span');       append.setAttribute("id", "show");       input.parentNode.appendChild(append);     }     var show = document.getElementById("show");     if(/^[0-9a-zA-Z]+$/.exec(value)){       show.innerHTML = 'Pass!';     }else{       show.innerHTML = 'Failed!';     }   },   _bind: function(){     var self = this;     self.input.addEventListener('keyup', function(){       self._render();     });   } }); window.onload = function(){   new JudgeInput({id: "input"}); }

但是,这样子,基本功能算是实现了,关键是不好扩展,没有面向对象的精髓。所以,针对目前的情况,我们准备建立一个 Base 基类,init  表示初始化,render 函数表示渲染,bind 函数表示绑定,destory 用来销毁,同时 get、set 方法提供获得和更改属性:

var Base = Class.extend({   init: function(config){     this._config = config;     this.bind();   },   get: function(key){     return this._config[key];   },   set: function(key, value){     this._config[key] = value;   },   bind: function(){     //以后构造   },   render: function(){     //以后构造   },   destory: function(){     //定义销毁方法   } });

基于这个 Base,我们修改 JudgeInput 如下:

var JudgeInput = Base.extend({   _getValue: function(){     return this.get('input').value;   },   bind: function(){     var self = this;     self.get('input').addEventListener('keyup', function(){       self.render();     });   },   render: function(){     var value = this._getValue();     if(!document.getElementById("show")){       var append = document.createElement('span');       append.setAttribute("id", "show");       input.parentNode.appendChild(append);     }     var show = document.getElementById("show");     if(/^[0-9a-zA-Z]+$/.exec(value)){       show.innerHTML = 'Pass!';     }else{       show.innerHTML = 'Failed!';     }   } }); window.onload = function(){   new JudgeInput({input: document.getElementById("input")}); }

比如,我们后期修改了判断条件,只有当长度为 5-10 的时候才会返回 success,这个时候能很快定位到 JudgeInput 的 render  函数:

render: function(){   var value = this._getValue();   if(!document.getElementById("show")){     var append = document.createElement('span');     append.setAttribute("id", "show");     input.parentNode.appendChild(append);   }   var show = document.getElementById("show");   //修改正则即可   if(/^[0-9a-zA-Z]{5,10}$/.exec(value)){     show.innerHTML = 'Pass!';   }else{     show.innerHTML = 'Failed!';   } }

以我目前的能力,只能理解到这里了。

关于一个组件的写法,从入门级到最终版本,一波三折,不仅要考虑代码的实用性,还要兼顾后期维护。JS 中实现面向对象,刚接触 JS  的时候,我能用简单的原型链来实现,后来看了一些文章,发现了不少问题,在看 John Resig 的 Class,感触颇深。还好,现在目的是实现了。

看完上述内容,你们对如何从一个组件的实现来深刻理解JS中的继承有进一步的了解吗?如果还想了解更多知识或者相关内容,请关注编程网VUE频道,感谢大家的支持。

--结束END--

本文标题: 如何从一个组件的实现来深刻理解JS中的继承

本文链接: https://lsjlt.com/news/86136.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • 如何从一个组件的实现来深刻理解JS中的继承
    今天就跟大家聊聊有关如何从一个组件的实现来深刻理解JS中的继承,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。其实,无论是写什么语言的程序员,最终的目...
    99+
    2024-04-02
  • 一文详解如何用原型链的方式实现JS继承
    目录原型链是什么通过构造函数创建实例对象用原型链的方式实现继承方法1:Object.create方法2:直接修改 [[prototype]]方法3:使用父类的实例总结今天讲一道经典的...
    99+
    2024-04-02
  • C++ 函数继承详解:如何处理继承中出现的二义性?
    解决继承中的二义性存在同名函数时,可以通过以下方法解决二义性:使用作用域解析符(::)指定函数所属的类。在派生类中重写基类函数。创建基类指针并指向派生类对象,然后使用指针调用基类函数。 ...
    99+
    2024-04-30
    c++ 函数继承 作用域
  • 如何实现一个angular版本的Message组件
    这篇文章主要介绍如何实现一个angular版本的Message组件,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!学习一个框架或库的最好方法是看官方文档,并着手去写例子。最近在利用空闲...
    99+
    2024-04-02
  • MySQL 8.0中如何通过Clone来实现一个远程从库的搭建
    这篇文章给大家分享的是有关MySQL 8.0中如何通过Clone来实现一个远程从库的搭建的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。环境如下Mater: 192.168.3.1...
    99+
    2024-04-02
  • JavaScript如何实现不要使用delete来删除一个数组中的项
    小编给大家分享一下JavaScript如何实现不要使用delete来删除一个数组中的项,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧!不要使用 delete 来删除一个数组中的项。使用&nb...
    99+
    2024-04-02
  • js如何根据json数据中的某一个属性来给数据分组
    这篇文章主要介绍js如何根据json数据中的某一个属性来给数据分组,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!如下所示:<!DOCTYPE html> <...
    99+
    2024-04-02
  • 如何从线条艺术到DIY实现一个网状体Net的js库
    本篇文章给大家分享的是有关如何从线条艺术到DIY实现一个网状体Net的js库,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。今天无意中看到一个可视化作品:WHAT MADE ME...
    99+
    2023-06-19
  • 如何实现webpack打包时排除其中一个css、js文件或单独打包一个css、js文件的方法
    这篇文章主要介绍了如何实现webpack打包时排除其中一个css、js文件或单独打包一个css、js文件的方法,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大...
    99+
    2024-04-02
  • js中如何实现一个获取页面ip的正则
    这篇文章将为大家详细讲解有关js中如何实现一个获取页面ip的正则,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。示例如下Javascrīpt:var arr=do...
    99+
    2024-04-02
  • JS组件bootstrap table分页实现过程中遇到的问题如何解决
    这篇“JS组件bootstrap table分页实现过程中遇到的问题如何解决”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“J...
    99+
    2023-07-04
  • angular如何实现一个列表的选择全选交互组件
    这篇文章给大家分享的是有关angular如何实现一个列表的选择全选交互组件的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。需求分析实现单选;实现全选;可以设置允许多选还是单选。如果...
    99+
    2024-04-02
  • 如何使用React Portals实现一个功能强大的抽屉组件
    本篇内容介绍了“如何使用React Portals实现一个功能强大的抽屉组件”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读...
    99+
    2024-04-02
  • 怎么在小程序中如何实现一个可截断的瀑布流组件
    这期内容当中小编将会给大家带来有关怎么在小程序中如何实现一个可截断的瀑布流组件,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。瀑布流是一种常见的布局方式,实现的方式有许多,比如直接分两列,然后控制在左右两列...
    99+
    2023-06-28
  • 如何使用C++实现一个简单的文件管理系统?
    如何使用C++实现一个简单的文件管理系统?概述:文件管理系统是计算机中非常重要的一个功能模块,它负责对计算机中的文件进行创建、修改、删除等操作。本文将介绍如何使用C++编程语言实现一个简单的文件管理系统,通过该系统,可以实现对文件的基本管理...
    99+
    2023-11-02
    C++ 实现 文件管理系统
  • 如何设计一个可靠的MySQL表结构来实现邮件发送功能?
    如何设计一个可靠的MySQL表结构来实现邮件发送功能?邮件发送功能是现代应用程序中常见的一个功能。在设计邮件发送功能时,一个重要的考虑是如何存储邮件相关的信息以及邮件的发送状态。MySQL是一个常用的关系型数据库,下面将介绍如何设计一个可靠...
    99+
    2023-10-31
    设计 邮件发送 MySQL表结构
  • 如何设计一个可靠的MySQL表结构来实现文件下载功能?
    如何设计一个可靠的MySQL表结构来实现文件下载功能?在很多应用中,文件下载功能是非常常见和重要的功能。为了实现文件下载功能,我们需要做好数据库表的设计,使其能够存储和管理文件的相关信息。本文将介绍如何设计一个可靠的MySQL表结构来实现文...
    99+
    2023-10-31
    MySQL表 结构 设计 文件 下载
  • 如何设计一个可靠的MySQL表结构来实现文件压缩功能?
    如何设计一个可靠的MySQL表结构来实现文件压缩功能?引言:在现代的应用程序和系统中,文件压缩是一项常用的功能,它可以显著减小文件的大小,节省存储空间,并提高传输效率。本文将介绍如何使用MySQL数据库来实现文件压缩功能,并提供相应的表结构...
    99+
    2023-10-31
    可靠设计 MySQL表结构 文件压缩功能
  • 如何设计一个可靠的MySQL表结构来实现文件上传功能?
    如何设计一个可靠的MySQL表结构来实现文件上传功能文件上传功能是现代网站应用中很常见的功能之一。为实现文件上传功能,我们需要设计一个可靠的MySQL表结构,用来存储上传的文件相关信息。本文将介绍如何设计这样一个表结构,并提供相应的代码示例...
    99+
    2023-10-31
    文件上传 可靠性 MySQL表结构设计
  • 如何设计一个可靠的MySQL表结构来实现文件存储功能?
    如何设计一个可靠的MySQL表结构来实现文件存储功能?目前,文件存储已经成为许多应用程序中不可或缺的一部分。在设计可靠的MySQL表结构时,我们需要考虑以下几个关键因素:文件存储方式文件存储可以采用两种方式:将文件直接存储在数据库中,或者将...
    99+
    2023-10-31
    可靠性设计 MySQL表结构设计 文件存储功能
软考高级职称资格查询
推荐阅读
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作