HTML5中的简单过渡效果

        网页的动画越来越多样化,而且HTML5越来越得到更多的支持,我们可以结合CSS3(主要用到transition和animation两种方式)和js脚本来实现很多复杂的动画和特效。这里举一个超级简单例子展示一下:

        我们实现一个按钮及其过渡效果,最后效果这样:效果

        先设置一个div,里面放一个链接a标签,文字为“点击按钮”:

 <div>
   <a href="http://www.ershing.cn">点击按钮</a>
 </div>

        然后设置外面的样式,使得div大概居于屏幕中间,背景颜色为浅蓝色:

 body{
   width:100%;
   height:100%;
   background:lightblue;
 }
 div{
   background:lightblue;
   height:60%;
   width:30%;
   margin:20% auto;
   text-align:center;
 }

        然后设置a标签的样式为白色边框,白色底,还有一些文字间隔大小等内容:

 a {
   display: block;
   margin:50px;
   color: white;
   text-decoration: none;
   font-family: sans-serif;
   font-size: 25px;
   line-height: 60px;
   border: 1px solid white;
   border-radius: 10px;
   text-align: center;
   text-indent :20px;
   letter-spacing: 20px;
 }

        再设置它的鼠标放置上面之后(hover)的样式:

 a:hover {
   color: purple;
   background: white;
   border:1px solid plum
 }

        好了,基本样式就搞定了,我们发觉这样每次放置鼠标上去和离开鼠标都有一种很突然的感觉,这里就要用到过度效果了,给a加一个匀速的0.5s转换效果:

 -webkit-transition: all .5s linear;
 transition: all .5s linear;

        好了,基本就搞定了,源码参考:源码

        效果可以参考:效果

        其实压根就是非常简单的用了一个transition过渡,不过结合css样式一起,我们可以得到很多我们想要的效果。

文章在我的github上的地址:点击跳转

原创文章,转载请注明出处!

知识共享许可协议
本文章采用知识共享署名-非商业性使用-相同方式共享 3.0 中国大陆许可协议进行许可。

CSS3中的图形

        CSS3出来之前,我们只能有矩形的图形,CSS3之后,clip-path和shape-outside可以做出很强大的图形功能,这里暂且不说。我们也可以通过border-radius、 border、 transform、 伪元素配合、gradient 渐变,我们能够作出非常多的几何图形,这里举例一下几个经典的样式:

        三角形:

 .traingle {
   width: 0;
   height: 0;
   border-left: 50px solid transparent;
   border-right: 50px solid transparent;
   border-bottom: 100px solid lightblue;
 }

        梯形:

.trapezoid {
    position: relative;
    width: 60px;
    padding: 60px;
}

.trapezoid::before {
    content: "";
    position: absolute;
    top: 0;
    right: 0;
    bottom: 0;
    left: 0;
    transform: perspective(20px) scaleY(1.3) rotateX(5deg);
    transform-origin: bottom;
    background: lightblue;
}

        六边形:

.hexagon {
    position: relative;
    width: 60px;
    border-bottom: 60px solid lightblue;
    border-left: 40px solid transparent;
    border-right: 40px solid transparent;
}

.hexagon::before {
    content: "";
    position: absolute;
    width: 60px;
    height: 0px;
    top: 60px;
    left: -40px;
    border-top: 60px solid lightblue;
    border-left: 40px solid transparent;
    border-right: 40px solid transparent;
}

        五角星:

.star {
    margin: 50px 0;
    position: relative;
    width: 0;
    border-right: 100px solid transparent;
    border-bottom: 70px solid lightblue;
    border-left: 100px solid transparent;
    transform: rotate(35deg) scale(.6);
}

.star:before {
    content: '';
    position: absolute;
    border-bottom: 80px solid lightblue;
    border-left: 30px solid transparent;
    border-right: 30px solid transparent;
    top: -45px;
    left: -65px;
    transform: rotate(-35deg);
}

.star:after {
    content: '';
    position: absolute;
    top: 3px;
    left: -105px;
    border-right: 100px solid transparent;
    border-bottom: 70px solid lightblue;
    border-left: 100px solid transparent;
    transform: rotate(-70deg);
}

        椭圆:

.ellipse {
    width: 120px;
    height: 160px;
    background-color: lightblue;
    border-radius: 50% 50% 50% 50% / 60% 60% 40% 40%;
}

        还有其他的一些可以直接看图:效果

        参考源码(反正我也是摘抄的):源码

 

python中的面向对象编程

        面向对象编程(Object Oriented Programming,OOP,面向对象程序设计)是编程的一种思想,需要用来“类”、“对象”等来实现,其实javascript也可以用面向对象编程,但是它的类是伪类,都是自己封装出来的语法糖,所以这里就说一下python中是如何实现面向对象编程的。

        面向对象有三大特性:封装、继承、多态。

        不想一一举例解释得太详细,因为这些都很基本,简单来说,其实封装就是将某些可能重复使用的代码封装起来,通过不同的场景进行调用;继承就是子类可以继承父类的方法,和儿子继承父亲的特征差不多意思;多态就是无需明确引用的对象是什么,只需要根据不同的对象表现出不同的行为方式,python实现多态和强类型语言有点不同,强类型语言需要指定参数类型,而python不需要,它的对象推断风格为“鸭子类型”,也就是“当看到一只鸟走起来像鸭子、游泳起来像鸭子、叫起来也像鸭子,那么这只鸟就可以被称为鸭子”。

        好了,直接来写一个类,一个子类,和一个实例化的对象:

# 创建一个Person类
class Person(object):
    def __init__(self, name):
        self.name = name

    def who(self):
        print('I am %s' % self.name)

# 创建一个Father类继承Person类
class Father(Person):
    def __init__(self,name,age):
        super(Father,self).__init__(name)
        self.age = age
    
    def who(self):
        print('I am %s, I am %s years old.' % (self.name,self.age))

    def saying(self):
        print('I am Father')

father = Father('Jack',30)
father.who()   #I am Jack, I am 30 years old.
father.saying()   #I am Father

        其实很简单,每个类中都有一个__init__函数用来初始化对象,而所有定义的函数中的self就是用来传入实例化的对象,这个很类似javascript中构造函数的this,其实都大同小异,子类可以继承父类的所有方法,也可以改写父类的方法(who),更可以创建自己的方法(saying)。

        好了,该说说类的成员了,类的成员分为三大类:字段、方法和属性。

        一、字段

        字段包括普通字段和静态字段。举个例子:

# 创建一个Person类
class Person(object):
    action = 'moving'
    def __init__(self,name):
        self.name = name

print(Person.action)   #'moving'
person = Person('Rose')
print(person.name)   #'Rose'

        可以看见,普通字段需要用类来访问,而静态字段要用对象来访问,这也很容易明白,一个函数里面的一个变量,当然通过这个函数来访问,而需要实例化时才传入的变量,当然是通过这个实例化的对象访问。

        二、方法

        方法包括普通方法、静态方法、类方法。举个例子:

# 创建一个Person类
class Person(object):
    action = 'moving'

    def __init__(self,name):
        self.name = name

    def who(self):
        print('I am %s' % self.name)

    @classmethod
    def own(cls):
        print('I am class method and','I am %s' % cls.action)

    @staticmethod
    def static():
        print('I am static method')

person = Person('Kate')
person.who()   #I am Kate
Person.own()   #I am class method and I am moving
Person.static()   #I am static method

        也很容易理解,普通方法就是通过实例化的对象访问的,而类方法和静态方法都是通过类访问,但是类方法要传入自身这个类作为参数。

        三、属性

        属性就只有普通属性一个了,但是却是非常简单的,和普通方法差不多,举个例子:

# 创建一个Person类
class Person(object):
    action = 'moving'

    def __init__(self,name):
        self.name = name

    def who(self):
        print('I am %s' % self.name)

    @property
    def run(self):
        print('I can run')


person = Person('Tom')
person.run   #I can run

        其实和普通方法没太大区别,定义时候加了个@property装饰器,只传入一个self,然后调用时候不用括号。

        不过要说一下属性的调用定义方式。

        类可分为经典类和新式类,而两者的区别就是是否继承自object,例如上面的Person就是新式类,前面的Father就是经典类,经典类定义属性只要前面加@property装饰器一种方法,而新式类,除了这种,还有两种:

# 创建一个Person类
class Person(object):
    action = 'moving'

    def __init__(self, name):
        self.name = name
        self.my_age = 18

    def who(self):
        print('I am %s' % self.name)

    @property
    def age(self):
        print('I am %d years old' % self.my_age)
        return self.my_age

    @age.setter
    def age(self, years):
        self.my_age = years

    @age.deleter
    def age(self):
        del self.my_age
        print('I delete my age now')


person = Person('Jason')
person.age   #I am 18 years old
person.age = 20   #修改年龄为20
person.age   #I am 20 years old
del person.age   #删除了普通字段my_age
person.age   #删除后获取字段值会报错
person.age = 26   #重新设置年龄my_age为26
person.age   #I am 26 years old

        其实很简单,一种访问、一种修改、一种删除。

        其实每一个类成员可分两种形式:公有成员(哪里都能访问)、私有成员(类内部才能访问,外面通过类访问也不行),除了特殊成员(下面讲到)外,在命名时候在前面加两个下划线(例如__what)就变为私有成员了。

        好了,该说一下特殊成员了,也就是特定的一些成员,有:

        __doc__:类的描述信息。

        __module__:当前操作的对象在哪个模块

        __class__:当前操作的对象的类是什么

        __init__:构造方法,通过类创建对象时,自动执行

        __del__:析构方法,对象在内存中被释放时,自动执行

        __call__:实例化后的对象后面加括号,自动执行。

        __dict__:类或对象中的所有成员

        __str__:打印对象输出该方法的返回值

        __getitem__、__setitem__、__delitem__:用于索引操作,分别表示获取、设置、删除数据

        __getslice__、__setslice__、__delslice__:三个分片操作

        __iter__:迭代器

        __new__ 和 __metaclass__:用来表示该类由谁来实例化创建

        关于python的面向对象编程,大概如此。

文章在我的github上的地址:点击跳转

原创文章,转载请注明出处!

知识共享许可协议
本文章采用知识共享署名-非商业性使用-相同方式共享 3.0 中国大陆许可协议进行许可。

CSS样式参考配色

        关于在css样式选择配色问题的时候,个人认为不能随便选择一个颜色,网上有很多配色方案,都可以参考一下,不同颜色的搭配方案是很符合个人审美观的,这里贴一下别人发我的图,应该都是网上截图过来的,这里借用一下:

        可以用QQ截图时候直接当吸管工具,查看颜色值。

文章在我的github上的地址:点击跳转

原创文章,转载请注明出处!

知识共享许可协议
本文章采用知识共享署名-非商业性使用-相同方式共享 3.0 中国大陆许可协议进行许可。

数据库中的分类搜索

        我们在学习数据库的过程中,可以很清楚地了解到,如果要搜索我们需要的数据,就要在WHERE之后添加我们的条件,当然,搜索可以用LIMIT要求获取某个范围的数据,也可以用ORDER  BY来对获取的数据进行排序输出,也可以用MAX(  )或者MIN(  )等函数获取其中的最值,但是如果要分类呢?要怎么写sql语句才能符合我们想获得的数据呢?

        下面举一个简单的例子:

        我这里有一个回复的表格,用来记录所有对某个主题的回复,我先创建这个表格:

CREATE TABLE IF NOT EXISTS reply(
        reply_id INT NOT NULL ,
        subject_id INT NOT NULL ,
        replyer_id INT NOT NULL ,
        reply_content VARCHAR(50) DEFAULT "" ,
        reply_time DATETIME NOT NULL ,
        PRIMARY KEY(reply_id)
      );

        这是一个比较简单的reply(回复)的表格,用来记录其他人对某个主题的回复记录,replt_id是主键,subject_id是回复的主题id,replyer_id是回复人的账号id,而reply_content就是回复的内容,reply_time是回复的时间。

        好了,大概了解了这个表是干什么的了。

        那么现在,如果我想做一件事,展示一下所有的回复内容,那么我应该如何做呢?如果单纯获取所有回复很简单,就一句话:

SELECT * FROM reply;

        但是,我想获取某个主题(假设这个主题id为888)的所有回复内容呢?也是一句话:

SELECT * FROM reply WHERE reply.subject_id=888;

        这也只是在后面加个WHERE条件而已,那如果我需要获取某个主题(假设这个主题id为888)的最后回复时间呢?可以这样写:

SELECT MAX(reply_time), reply_id FROM reply 
WHERE reply.subject_id=888;

        可以用最大值代表最后的回复时间。那又如果我想获取好几个主题(假设这几个主题id为111,333,888)的最后回复时间呢?

        可能瞬间你会想到用IN,这样:

SELECT MAX(reply_time), reply_id FROM reply 
WHERE reply.subject_id IN (111,333,888);

        但是很显然,这是错的,因为你只是在三个主题(111,333,888)下的所有情况搜索出最后的回复时间,而没有每一条主题的回复时间,所以结果最多只有一条。

        当然了,你可以用UNION方法达到效果:

SELECT MAX(reply_time), reply_id FROM reply 
WHERE reply.subject_id=111
UNION
SELECT MAX(reply_time), reply_id FROM reply 
WHERE reply.subject_id=333
UNION
SELECT MAX(reply_time), reply_id FROM reply 
WHERE reply.subject_id=888;

        但是我只给你一个数组呢,要你用IN方法写出来呢?

        那就要从最根本查找语句的逻辑出发了,因为我们是查找某些主题下的最后回复时间,那么我们从整个表中查找的话,那就只需要给我所有的最后回复时间啊,我先不管最后回复时间是怎样来的,我也可以先写出这样的语句:

SELECT reply_time, reply_id FROM reply 
WHERE ……;

        好了,这个时候我们就要考虑怎样获取到所有的主题,这里就要借用一个技巧,借用一下别名,因为我们需要找出所有的主题,那么如何找,那就需要用两个表来确认subject_id相等的地方,那就可以找出所有同一主题的数据,再从中提取最大值,那就可以了:

SELECT reply_time, reply_id FROM reply AS a
WHERE 
(SELECT MAX(b.reply_time) FROM reply AS b 
WHERE
a.subject_id=b.subject
);

        最后,再加上需要查找的subject_id就可以了:

SELECT reply_time, reply_id FROM reply AS a
WHERE 
(SELECT MAX(b.reply_time) FROM reply AS b 
WHERE
a.subject_id=b.subject AND b.subject IN (111,333,888)
);

        上面就是一个简单的分类搜索语句,但是实际应用中,有很多远远复杂的要求,所以对sql语句的掌握也是非常重要的。

文章在我的github上的地址:点击跳转

原创文章,转载请注明出处!

知识共享许可协议
本文章采用知识共享署名-非商业性使用-相同方式共享 3.0 中国大陆许可协议进行许可。

数据库中的事务

        在数据库中,事务就是一个执行操作的工作单元。说得简单点,就是一个包含多个数据库操作的任务。例如,你先查这个表数据,然后再删那个表数据,再去创建一个新数据,这样的一系列的操作组成一个事务来管理。

        事务有四个标准属性:ACID。就是:原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)、持久性(Durability)。

        其实我不太喜欢太多的名词,在我看来,事务就是可以让你这些操作均成功完成,若其中一个操作发生错误,则全部回滚到最初状态。

        关于这个事务处理,基于它的特点,所以有一个很重要的特征,就是事务中的每个sql语句是不会立即提交(COMMIT)的,只会当你需要提交的时候,或者结束事务的时候才统一提交(COMMIT)的。

        举一个简单的例子,我在使用SQLite(SQLite是一个轻量级的数据库,无需建立数据库连接,只需引入数据文件即可)的时候遇到了一个问题,我在一个服务器运行之前,需要检测一下数据库中的区域信息,也就是所有的省市区的常规信息的时候,执行一个sql文件(这个区域信息可以参考这个文件:区域信息)中的语句,发觉很慢,超级慢,打开SQLite Expert Pro(一款数据库可视化工具)观察,等了很久很久,然后点击一下,就崩了,发觉这样执行完全不行啊。然后用可视化工具直接复制语句进去执行,等了很久出来了部分数据,然后报错了。

        最后就找到需要用事务处理这种办法,因为sql语句中有好几千条数据,如果每读取一条执行语句都要commit一下,那么这段语句就要commit几千次了,对数据库的负担是很大的,虽然这种做法在MySQL中可以很快就完成了,但是在SQLite这种轻量级的数据库中却不是一件容易的事情,所以我在所有语句的前面加入语句:

BEGIN TRANSACTION;

        然后在所有语句最后加入语句:

END TRANSACTION;   # 或者COMMIT;

        这样就将整段语句作为事务来处理了,然后执行的时候就一瞬间就插入到数据库中了,所以数据库中的事务是非常有用的。

文章在我的github上的地址:点击跳转

原创文章,转载请注明出处!

知识共享许可协议
本文章采用知识共享署名-非商业性使用-相同方式共享 3.0 中国大陆许可协议进行许可。

python中函数的参数类型

        学习python的过程中,少不了对函数的学习,而python中函数的参数又跟它自身数据类型有很大关系,所以有其自身的独特性,但是毕竟都是编程语言,跟其他语言都有相通的地方,这里就列举一下它的各种参数类型:

        一、位置参数

        就是一个萝卜一个坑,是你自己的就占自己的坑,例如:

def devided(x, y):
    return x / y

print(devided(0, 3))   # 0.0
print(devided(3, 0))   # 报错

        这个位置是x的,你传参数进去,它就对应放在x那里,是y的就会放在y的那里,这就是位置参数。但要注意这个位置参数是必填参数,调用必须传递的。

        二、默认参数

        就是你不传递,它就默认一个参数,这个也很好理解,例如:

def devided(x, y=1):
    return x / y

print(devided(3))   # 3.0

        就是我前面还是按位置参数传递,而到了有默认参数的地方,如果我不传递的话,那它就会按照函数定义的默认值来传值。

        但是这里要注意的是,默认参数必须放在位置参数之后,例如上面函数定义时候不能写devided(x=1, y),就是必传的参数必须放在前面,爱传不传的参数(默认参数)必须放后面,你想一下自己调用函数时候就知道了。

        三、不定长参数

        如果我们传递进去的参数不确定传多少个怎么办,那就需要不定长参数了,例如:

def calc(*numbers):
    sum = 0
    for i in numbers:
        sum += i
    return sum

print(calc(1,3,8))   # 12

        看函数里面的操作,可以知道numbers是一个可迭代对象,实则上就是一个tuple,当然了,你也可以不用到它的所有值,反正就是在不定长参数前面加一个 * 符号就行了。

        这个不定长参数,就和javascript中的函数参数有些区别了,javascript中的函数参数本来就是不定长的,你想传多少都没有问题,因为里面有一个arguments对象保存你传进来的值,所以上面这个例子,用javascript来写可以写成这样:

function numbers() {
    var sum = 0;
    for (i = 0; i < arguments.length; i++) {
        sum += arguments[i];
    }
    return sum;
}

console.log(numbers(1, 3, 8));   // 12

        所以有时候也挺喜欢用javascript这样打补丁的方式添加函数功能,只要判断后面某个参数在不在就行了。

        扯远了,回过头来,我们在传入不定长参数的时候一个一个传挺麻烦的啊,所以也可以在调用的时候传入一个list或者tuple,在前面加个 * 符号就行了,例如:

def calc(*numbers):
    sum = 0
    for i in numbers:
        sum += i
    return sum

inputList = [1,3,8];
print(calc(*inputList))   # 12

        这样多方便,像javascript中的 … 解构符号。

        四、关键字参数

        其实前面写到,js默认就是可变长参数,所以可以轻易扩展函数功能,但是python怎样做的呢,它是通过传入不确定的键值对来达到的,所以这个关键字参数也很好理解,就是key-value这样形式的参数。

        这种key-value在python中就是dict(字典),其实写法类似前面的不定长参数,不过多了一个 * 符号,例如:

def introduction(name, age, **others):
    print('name is:', name)
    print('age is:', age)
    print('others is:', others)
introduction('Jade', 15, sex='female', height='170cm')
# 打印结果为:
# name is: Jade
# age is: 15
# others is: {'sex': 'female', 'height': '170cm'}

        所以也很清楚了,类似上面的不定长参数传参,我们也可以直接传一个dict,像这样:

def introduction(name, age, **others):
    print('name is:', name)
    print('age is:', age)
    print('others is:', others)
details = {'sex':'female', 'height':'170cm'}
introduction('Jade', 15, **details)
# 打印结果为:
# name is: Jade
# age is: 15
# others is: {'sex': 'female', 'height': '170cm'}

        和前面都很类似对吧,但是这里打印的数据中的键值其实没有排序的,所以可能每次打印的顺序都不同,但是键值对还是那样的键值对。

        五、命名关键字参数

        其实我觉得这个名称和作用都很坑爹,因为关键字参数是不限制传入的关键字的,所以如果你要限制怎么办,那就要用命名关键字参数了,它是用一个 * 来分隔的,例如:

def introduction(name, age, *, sex, height):
    print('name is %s, age is %s, sex is %s and heighe is %s' %
          (name, age, sex, height))

details = {'sex': 'female', 'height': '170cm'}
introduction('Jade', 15, **details)
# 打印结果为:
# name is Jade, age is 15, sex is female and heighe is 170cm

# 如果数据多了其他键值对
details = {'sex': 'female', 'height': '170cm', 'weight': '50kg'}
introduction('Jade', 15, **details)   # 报错

        所以可以看到,这个中间的 * 符号就是限制了关键字参数的关键字,所以叫做命名关键字参数(很绕口),那如果中间又有一个可变成参数呢?例如:

def introduction(name, age, *args, sex, height):
    print(name, age, args, sex, height)

        由于可变长参数已经有个 * 符号了,所以后面就无需用 * 符号隔开了。

        好了,这就是python函数中的几种参数类型了,但是要注意的是,参数定义时候要按照这样的顺序:位置参数(必选参数)、默认参数、不定长参数、命名关键字参数和关键字参数。

        由于*args代表不定长参数,而**others代表关键字参数,所以我们可以用通式参数代表所有函数:

        所以可以看到,这个中间的 * 符号就是限制了关键字参数的关键字,所以叫做命名关键字参数(很绕口),那如果中间又有一个可变成参数呢?例如:

def func(*args, **others):
     print(args, others)

文章在我的github上的地址:点击跳转

原创文章,转载请注明出处!

知识共享许可协议
本文章采用知识共享署名-非商业性使用-相同方式共享 3.0 中国大陆许可协议进行许可。

大文件分块上传、断点续传

        很多时候我们需要上传文件,都会用到直接form-data的方式上传,但是如果文件太大呢,例如一个500MB的文件,服务器端对请求数据有大小要求限制怎么办,不可能整个大文件传输,又或者你想读取文件内容怎么办,这么大的文件全部读入内存?浏览器不答应吧。所以我们就想到分块的方法。

        主要用到的是HTML 5 的file相关的api,这里不讨论相关读取文件内容(其实也不过是用了FileReader 对象的readAsArrayBuffer方法而已),这里单纯实现文件分块,然后上传,当然还有断点续传。下面只展示关键代码。

        废话少说,先来个HTML的框架大致内容用于测试,一个选择文件按钮,一个上传按钮:

<input type="file" id="files" name="file" />
<input id="uploadBtn" type="button" value="上传">

        然后开始script标签内容了,先DOM获取文件和按钮、并设置上传的地址:

var input = document.getElementById('files');
var upload = document.getElementById('uploadBtn');
//自己建立一个测试的服务器,后面会提到后端的代码
var host = 'http://localhost:10000/attachment/upload'  

        好了,获取到文件之后,就要开始切割了,切割考虑到不同浏览器的兼容性问题,所以要做个判断:

var blob;
if (file.webkitSlice) {
      blob = file.webkitSlice(fileLoaded, fileLoaded + block);
} else if (file.mozSlice) {
       blob = file.mozSlice(fileLoaded, fileLoaded + block);
} else if (file.slice) {
      blob = file.slice(fileLoaded, fileLoaded + block);
} else {
      alert('不支持分段读取!');
}

        切割完之后,就要放进去新创建的FormData对象里面了:

var formData = new FormData();
formData.append("fileBlob", blob);

        最后,用jquery的ajax异步上传,在回调的地方判断文件是否完成整个切割上传,如果还没上传完成,继续切割继续上传:

$.ajax({
    url: host+'/base_data_service/pic/upload',
    type: 'POST',
    data: formData,
    cache: false,
    contentType: false,
    processData: false,
    success: function (data) {
        if (data.guid) {
            //用guid来标识某个文件
        }
        if (percent < 1) {
            // 继续切割下一块
        } else {
            // 结束
            console.log('已完成文件存储');
        }
        return;
    },
    error: function (data) {
        console.log('上传出现错误', data);
    }
});

        至于怎样断点续传呢?就是在每次回调的地方存储文件已经切割上传的位置,那么即使断网了,再连上去下一次也知道从哪里开始继续切割了。

        参考代码并不完全严谨,只是提供一个总体思路。

        完整的前端代码可以参考:前端源码参考

        当然了,这个前端代码还是要配合后端的操作的,这里后端用node写的,也可以参考一下:后端源码参考

文章在我的github上的地址:点击跳转

原创文章,转载请注明出处!

知识共享许可协议
本文章采用知识共享署名-非商业性使用-相同方式共享 3.0 中国大陆许可协议进行许可。