10.20stark组件已经完工

2018-10-20 19:37:31

stark组件已经做完!基本上和Django的admin一样!

放上github连接:https://github.com/TrueNewBee/pythonDemo/blob/master/stark_demo.rar

放上正版的stark组件: https://github.com/TrueNewBee/pythonDemo/blob/master/stark.zip

stark组件已经完成,明天整理Django博客!

后面的就是crm项目啦!

越努力,与幸运!永远不要高估自己!

知识点  test.py

子类继承父类 , 然后和父类的类型一样 isinstance()

modelForm 把  model.Model 转换成 form.Form

ChoiceFiled
ModelChoiceFiled(ChoiceFiled) ---- select(单选)
MultiModelChoiceFiled (ModelChoiceFiled)----select(多选)

class Book(model.Model):
    title = models.CharField(max_length=32)
    price = models.IntegerField()
    publish=model.Foreignkey("Publish")
    authors=model.ManyToMany("Author")

from django.forms import ModelForm
class BookForm(ModelForm):
    class Meta:
        model=Book
        fields="__all__"

from django import forms
class BookForm(forms.Form):
    title=forms.CharField(max_length=32)
    price=forms.IntegerField()
    publish = forms.ModelChoiceFiled("Publish")
    authors = forms.ModelMultipleChoiceField("Author")

form=BookForm()

for i in form:
    if isinstance(i,ModelChoiceFiled):
        pass 

‘‘‘

pop功能:

1 如何在一对多和多对多字段后渲染 +

2 +对应的跳转路径

上述两步实现逻辑

def add_view(self, request):
    # 实例化form类对象
    ModelFormDemo = self.get_modelform_class()
    form = ModelFormDemo()
    for bfield in form:
        # 这个可以看源码,然后类调用所需属性
        from django.forms.boundfield import BoundField
        print(bfield.field)             # 字段对象
        print("name",bfield.name)       # 字段名(字符串)
        print(type(bfield.field))       # 字段类型
        # 看源码可得 多对多和一对多是ModelChoiceFiled的类型
        from django.forms.models import ModelChoiceField
        if isinstance(bfield.field, ModelChoiceField):
            # 增加一个属性,传给前端做判断,是否显示这个 +按钮
            bfield.is_pop = True
            print("=======>", bfield.field.queryset.model) # 一对多或者多对多字段的关联模型表
            # 通过下面两个方法,找到表和app名字
            related_model_name = bfield.field.queryset.model._meta.model_name
            related_app_label = bfield.field.queryset.model._meta.app_label
            # 拼接url传给前端
            _url = reverse("%s_%s_add" % (related_app_label, related_model_name))
            # 创建一个新的属性url 给前端调用
            bfield.url = _url+"?pop_res_id=id_%s" % bfield.name

上面是get请求,下面是这个函数post请求的逻辑

# POST请求
        if request.method == "POST":
            form = ModelFormDemo(request.POST)
            if form.is_valid():
                obj = form.save()       # 保存数据,并返回一个obj
                pop_res_id = request.GET.get("pop_res_id")
                # 判断是点击+按钮带参数访问,还是通过add页面直接访问的
                if pop_res_id:
                    res = {"pk": obj.pk, "text": str(obj), "pop_res_id": pop_res_id}
                    return render(request, "pop.html", {"res": res})
                else:
                    return redirect(self.get_list_url())
        return render(request, "add_view.html", locals())

3 保存添加记录同时,将原页面的对应的下拉菜单中添加该记录
通过js方法!

from.html

<script>
    // 打开一个新的窗口添加数据
    function pop(url) {
        window.open(url,"","width=600,height=400,top=100,left=100")
    }
</script>

pop.html  (作用就是一个桥梁,传给父类页面相应参数,然后关闭)

<script>
    // 调用父类的方法,并把相应参数传给父类
    window.opener.pop_response(‘{{ res.pk }}‘,"{{ res.text }}",‘{{ res.pop_res_id }}‘)
    // 传过去后直接关闭页面,由于响应很快,时间可以忽略
    window.close()
</script>

add.html(接受子页面传入的参数,然后通过jQuery方法把传入的数据直接添加到select框中默认选中)

<script>
   function pop_response (pk,text,id) {

       console.log(pk,text,id);
        // 接受子页面传入的参数,并通过jQuery,添加相应的标签和值
        // 选择哪一个select标签
        // option的文本值和value值

       var $option=$(‘<option>‘);  //  <option></option>
       $option.html(text); //  <option>南京出版社</option>
       $option.val(pk);     //  <option value=111>南京出版社</option>
       $option.attr("selected","selected") ;   //  <option value=111>南京出版社</option>
       $("#"+id).append($option)

   }
</script>

然后附上这个stark组件的主要代码!主要看逻辑实现!!想看源码就去github下一下!源码里面都注释好啦!!!!!

stark/stark.py

from django.conf.urls import url
from django.shortcuts import render, redirect
from django.urls import reverse
from django.utils.safestring import mark_safe
from django.forms import ModelForm
from stark.utils.page import Pagination
from django.db.models import Q
from django.db.models.fields.related import ForeignKey
from django.db.models.fields.related import ManyToManyField
import copy
"""Stark组件!2018-10-20 19:39:08功能简介:        1. 使用方法和Django的admin一样,需要在strak里面注册,详情看app01/stark.py        2. 实现了对不同表的url的各级分发        3. 用户可以自定义配置表的现实信息 详情可以看app01/stark.py        4. 实现了对表添加数据pop的功能!        5. 最强大就是,你可以拿去直接用,和admin一样,而且不需要超级用户!        2333333333333333333333333333333"""
class ShowList(object):
    # 这是一个配置类的对象初始化
    def __init__(self, config, data_list, request):
        self.config = config
        self.data_list = data_list
        self.request = request
        # 分页
        data_count = self.data_list.count()
        current_page = int(self.request.GET.get("page", 1))
        base_path = self.request.path
        self.pagination = Pagination(current_page, data_count, base_path, self.request.GET, per_page_num=3, pager_count=11,)
        self.page_data = self.data_list[self.pagination.start:self.pagination.end]
        # actions   获取actions这个配置类的列表
        self.actions = self.config.actions  # [patch_init,]

    # 处理filter字段连接
    def get_filter_linktags(self):
        """用了两次for循环,在算法上有点缀余!不过可以用类或函数封装只是懒-.-能力欠缺!"""
        print("list_filter:", self.config.list_filter)
        link_dic = {}
        for filter_field in self.config.list_filter:  # ["title","publish","authors",]
            params = copy.deepcopy(self.request.GET)
            cid = self.request.GET.get(filter_field, 0)
            print("filter_field", filter_field)  # "publish"
            # 通过_meta.get_field方法,获取该表名对象
            filter_field_obj = self.config.model._meta.get_field(filter_field)

            print("filter_field_obj", filter_field_obj)
            print(type(filter_field_obj))
            # print("rel...",filter_field_obj.rel.to.objects.all())

            # 判断一下 如果是多对多或一对多类型的
            if isinstance(filter_field_obj, ForeignKey) or isinstance(filter_field_obj, ManyToManyField):
                # 拿到表的所有QuerySet对象
                data_list = filter_field_obj.rel.to.objects.all()  # 【publish1,publish2...】
            else:
                # 这个则是自定义过滤字段
                data_list = self.config.model.objects.all().values("pk", filter_field)
                print("data_list", data_list)

            temp = []
            # 处理 全部标签
            if params.get(filter_field):
                # 如果url如果存在参数 则del
                del params[filter_field]
                temp.append("<a href=‘?%s‘>全部</a>" % params.urlencode())
            else:
                # 反之加上class 增加颜色
                temp.append("<a  class=‘active‘ href=‘#‘>全部</a>")

            # 处理 数据标签
            for obj in data_list:
                # 循环列表中每个QuerySet的对象然后取到相应的值
                if isinstance(filter_field_obj, ForeignKey) or isinstance(filter_field_obj, ManyToManyField):
                    pk = obj.pk
                    text = str(obj)
                    params[filter_field] = pk
                else:  # data_list= [{"pk":1,"title":"go"},....]
                    pk = obj.get("pk")
                    text = obj.get(filter_field)
                    params[filter_field] = text

                _url = params.urlencode()
                if cid == str(pk) or cid == text:
                    link_tag = "<a class=‘active‘ href=‘?%s‘>%s</a>" % (_url, text)
                else:
                    link_tag = "<a href=‘?%s‘>%s</a>" % (_url, text)
                temp.append(link_tag)

            link_dic[filter_field] = temp
        return link_dic

    # 获取下拉框 用户配置的action_list
    def get_action_list(self):
        temp = []
        for action in self.actions:
            #  [{"name":""patch_init,"desc":"批量初始化"}]
           temp.append({
               "name": action.__name__,
               "desc": action.short_description
           })
        return temp

    # 构建表头
    def get_header(self):
        header_list = []
        print("header", self.config.new_list_play())
        # [checkbox,"pk","name","age",edit ,deletes]     【checkbox ,"__str__", edit ,deletes】
        for field in self.config.new_list_play():

            if callable(field):
                # header_list.append(field.__name__)
                val = field(self.config, header=True)
                header_list.append(val)

            else:
                if field == "__str__":
                    header_list.append(self.config.model._meta.model_name.upper())
                else:
                    # header_list.append(field)
                    val = self.config.model._meta.get_field(field).verbose_name
                    header_list.append(val)
        return header_list

    # 构建表单数据
    def get_body(self):
        # 构建表单数据
        new_data_list = []
        for obj in self.page_data:
            temp = []
            for filed in self.config.new_list_play():  # ["__str__",]      ["pk","name","age",edit]
                if callable(filed):
                    val = filed(self.config, obj)
                else:
                    # 这里捕获一下异常,因为默认的list_play里面有__str__ 直接找不到该字段
                    # 所以直接用getattr方法就行啦!
                    try:
                        field_obj = self.config.model._meta.get_field(filed)
                        if isinstance(field_obj, ManyToManyField):
                            # getattr()仅取到Object, 然后.all() 则可以取到对象
                            ret = getattr(obj, filed).all()
                            t = []
                            for obj in ret:
                                t.append(str(obj))
                            val = ",".join(t)

                        else:
                            val = getattr(obj, filed)
                            if filed in self.config.list_display_links:
                                # "app01/userinfo/(\d+)/change"
                                _url = self.config.get_change_url(obj)
                                val = mark_safe("<a href=‘%s‘>%s</a>" % (_url, val))
                    except Exception as e:
                        val = getattr(obj, filed)
                temp.append(val)
            new_data_list.append(temp)
        return new_data_list

class ModelStark(object):
    # 默认的list_play[]
    list_display = ["__str__", ]
    list_display_links = []
    modelform_class = None
    search_fields = []
    actions = []
    list_filter = []

    def __init__(self, model, site):
        self.model = model
        self.site = site

    # 默认的批量删除action
    def patch_delete(self, request, queryset):
        queryset.delete()
    patch_delete.short_description = "批量删除"

    # 配置表头: 删除 编辑,复选框
    def edit(self, obj=None, header=False):
        """编辑"""
        if header:
            return "操作"
        # return mark_safe("<a href=‘%s/change‘>编辑</a>"%obj.pk)
        _url = self.get_change_url(obj)
        return mark_safe("<a href=‘%s‘>编辑</a>" % _url)

    def deletes(self, obj=None, header=False):
        """删除"""
        if header:
            return "操作"
        # return mark_safe("<a href=‘%s/change‘>编辑</a>"%obj.pk)
        _url = self.get_delete_url(obj)
        return mark_safe("<a href=‘%s‘>删除</a>" % _url)

    def checkbox(self, obj=None, header=False):
        """复选框"""
        if header:
            return mark_safe(‘<input id="choice" type="checkbox">‘)
        # value的值不能写死,
        return mark_safe(‘<input class="choice_item" type="checkbox" name="selected_pk" value="%s">‘ % obj.pk)

    # 获取配置类的表头信息
    def get_modelform_class(self):
        """获取表的配置类"""
        if not self.modelform_class:
            # 如果表的配置类为空
            class ModelFormDemo(ModelForm):
                class Meta:
                    model = self.model
                    fields = "__all__"
                    labels = {
                        ""
                    }
            return ModelFormDemo
        else:
            return self.modelform_class

    # 添加的视图函数
    def add_view(self, request):
        # 实例化form类对象
        ModelFormDemo = self.get_modelform_class()
        form = ModelFormDemo()
        for bfield in form:
            # 这个可以看源码,然后类调用所需属性
            from django.forms.boundfield import BoundField
            print(bfield.field)             # 字段对象
            print("name",bfield.name)       # 字段名(字符串)
            print(type(bfield.field))       # 字段类型
            # 看源码可得 多对多和一对多是ModelChoiceFiled的类型
            from django.forms.models import ModelChoiceField
            if isinstance(bfield.field, ModelChoiceField):
                # 增加一个属性,传给前端做判断,是否显示这个 +按钮
                bfield.is_pop = True
                print("=======>", bfield.field.queryset.model) # 一对多或者多对多字段的关联模型表
                # 通过下面两个方法,找到表和app名字
                related_model_name = bfield.field.queryset.model._meta.model_name
                related_app_label = bfield.field.queryset.model._meta.app_label
                # 拼接url传给前端
                _url = reverse("%s_%s_add" % (related_app_label, related_model_name))
                # 创建一个新的属性url 给前端调用
                bfield.url = _url+"?pop_res_id=id_%s" % bfield.name
        # POST请求
        if request.method == "POST":
            form = ModelFormDemo(request.POST)
            if form.is_valid():
                obj = form.save()       # 保存数据,并返回一个obj
                pop_res_id = request.GET.get("pop_res_id")
                # 判断是点击+按钮带参数访问,还是通过add页面直接访问的
                if pop_res_id:
                    res = {"pk": obj.pk, "text": str(obj), "pop_res_id": pop_res_id}
                    return render(request, "pop.html", {"res": res})
                else:
                    return redirect(self.get_list_url())
        return render(request, "add_view.html", locals())

    # 删除的视图函数
    def delete_view(self, request, id):
        url = self.get_list_url()
        if request.method == "POST":
            self.model.objects.filter(pk=id).delete()
            return redirect(url)
        return render(request, "delete_view.html", locals())

    # 编辑的视图函数
    def change_view(self, request, id):
        ModelFormDemo = self.get_modelform_class()
        edit_obj = self.model.objects.filter(pk=id).first()
        if request.method == "POST":
            form = ModelFormDemo(request.POST, instance=edit_obj)
            if form.is_valid():
                form.save()
                return redirect(self.get_list_url())
            return render(request, "add_view.html", locals())
        form = ModelFormDemo(instance=edit_obj)
        return render(request, "change_view.html", locals())

    # 搜索的视图函数
    def get_serach_conditon(self, request):
        key_word = request.GET.get("q", "")
        self.key_word = key_word
        search_connection = Q()
        if key_word:
            # self.search_fields # ["title","price"]
            search_connection.connector = "or"
            # 用Q的这种添加方法可以添加字符串
            for search_field in self.search_fields:
                # search_field+"__contains"  ---->  title__contains="o"   就是title字段里面包含字母o的
                search_connection.children.append((search_field + "__contains", key_word))
        return search_connection

    # 过滤filter的视图函数
    def get_filter_condition(self, request):
        filter_condition = Q()
        for filter_field, val in request.GET.items():
            if filter_field in self.list_filter:
                filter_condition.children.append((filter_field, val))
        return filter_condition

    # 查看的视图函数
    def list_view(self, request):
        if request.method == "POST":  # action
            print("POST:", request.POST)
            action = request.POST.get("action")  # patch_init
            selected_pk = request.POST.getlist("selected_pk")
            action_func = getattr(self, action)
            queryset = self.model.objects.filter(pk__in=selected_pk)
            ret = action_func(request, queryset)
            # return ret
        # 获取search的Q对象
        search_connection = self.get_serach_conditon(request)

        # 获取filter构建Q对象
        filter_condition = self.get_filter_condition(request)

        # 筛选获取当前表所有数据
        data_list = self.model.objects.all().filter(search_connection).filter(filter_condition)  # 【obj1,obj2,....】

        # 按这ShowList展示页面
        showlist = ShowList(self, data_list, request)

        # 构建一个查看URL
        add_url = self.get_add_url()
        return render(request, "list_view.html", locals())

    #  获取用户配置类里面的list_play[]
    def new_list_play(self):
        temp = []
        temp.append(ModelStark.checkbox)
        temp.extend(self.list_display)
        if not self.list_display_links:
            temp.append(ModelStark.edit)
        temp.append(ModelStark.deletes)
        return temp

    # 获取用户配置类里面的actions 这个列表
    def new_actions(self):
        temp=[]
        temp.append(ModelStark.patch_delete)
        temp.extend(self.actions)
        return temp

    """把url进行反向解析,解耦到各自的函数中,函数中直接返回了对应的url"""
    # 获取修改页面的url
    def get_change_url(self, obj):
        model_name = self.model._meta.model_name
        app_label = self.model._meta.app_label

        _url = reverse("%s_%s_change" % (app_label, model_name), args=(obj.pk,))

        return _url

    # 获删除改页面的url
    def get_delete_url(self, obj):
        model_name = self.model._meta.model_name
        app_label = self.model._meta.app_label

        _url = reverse("%s_%s_delete" % (app_label, model_name), args=(obj.pk,))

        return _url

    # 获取添加页面的url
    def get_add_url(self):

        model_name = self.model._meta.model_name
        app_label = self.model._meta.app_label

        _url = reverse("%s_%s_add" % (app_label, model_name))

        return _url

    # 获取查看页面的url
    def get_list_url(self):

        model_name = self.model._meta.model_name
        app_label = self.model._meta.app_label

        _url = reverse("%s_%s_list" % (app_label, model_name))

        return _url

    # 二级url分发函数
    def get_urls_2(self):
        temp = []
        model_name = self.model._meta.model_name
        app_label = self.model._meta.app_label
        temp.append(url(r"^add/", self.add_view, name="%s_%s_add" % (app_label, model_name)))
        temp.append(url(r"^(\d+)/delete/", self.delete_view, name="%s_%s_delete" % (app_label, model_name)))
        temp.append(url(r"^(\d+)/change/", self.change_view, name="%s_%s_change" % (app_label, model_name)))
        temp.append(url(r"^$", self.list_view, name="%s_%s_list" % (app_label, model_name)))
        return temp

    @property
    def urls_2(self):
        print(self.model)
        return self.get_urls_2(), None, None

class StarkSite(object):
    def __init__(self):
        self._registry = {}

    def register(self, model, stark_class=None):
        if not stark_class:
            stark_class = ModelStark

        self._registry[model] = stark_class(model, self)

    # 一级分发url函数
    def get_urls(self):
        temp = []
        for model, stark_class_obj in self._registry.items():
            model_name = model._meta.model_name
            app_label = model._meta.app_label
            # 分发增删改查
            temp.append(url(r"^%s/%s/" % (app_label, model_name), stark_class_obj.urls_2))

            ‘‘‘
            url(r"^app01/userinfo/",UserConfig(Userinfo).urls_2),
            url(r"^app01/book/",ModelStark(Book).urls_2), 

            ‘‘‘
        return temp

    @property
    def urls(self):

        return self.get_urls(), None, None

# 创建stark的一个单例对象
site = StarkSite()

app01/stark.py

from stark.service.stark import site,ModelStark
from django.shortcuts import HttpResponse
from .models import *
from django.forms import ModelForm

class BookModelForm(ModelForm):
    class Meta:
        model = Book
        fields = "__all__"
        labels = {
            "title": "书籍名称",
            "price": "价格"
        }

class BookConfig(ModelStark):
    # 自定义展示列表
    list_display = ["title", "price", "publishDate", "publish", "authors"]
    # 自定义设置字段为连接
    list_display_links = ["title"]
    modelform_class = BookModelForm
    # 自定义搜索字段
    search_fields = ["title", "price"]

    def patch_init(self, request, queryset):
        print(queryset)
        queryset.update(price=123)
        return HttpResponse("批量初始化OK")
    patch_init.short_description = "批量初始化"
    # 自定义处理函数
    actions = [patch_init]
    # 自定义筛选字段
    list_filter=["title","publish","authors",]

site.register(Book, BookConfig)
site.register(Publish)
site.register(Author)
site.register(AuthorDetail)

app01/models.py

from django.db import models

# Create your models here.

from django.db import models

# Create your models here.
from django.db import models

# Create your models here.

class Author(models.Model):
    nid = models.AutoField(primary_key=True)
    name=models.CharField( max_length=32)
    age=models.IntegerField()

    # 与AuthorDetail建立一对一的关系
    authorDetail=models.OneToOneField(to="AuthorDetail",on_delete=models.CASCADE)

    def __str__(self):
        return self.name

class AuthorDetail(models.Model):

    nid = models.AutoField(primary_key=True)
    birthday=models.DateField()
    telephone=models.BigIntegerField()
    addr=models.CharField( max_length=64)

    def __str__(self):
        return self.telephone

class Publish(models.Model):
    nid = models.AutoField(primary_key=True)
    name=models.CharField( max_length=32)
    city=models.CharField( max_length=32)
    email=models.EmailField()
    def __str__(self):
        return self.name

class Book(models.Model):

    nid = models.AutoField(primary_key=True)
    title = models.CharField( max_length=32)
    publishDate=models.DateField()
    price=models.DecimalField(max_digits=5,decimal_places=2)

    # 与Publish建立一对多的关系,外键字段建立在多的一方
    publish=models.ForeignKey(to="Publish",to_field="nid",on_delete=models.CASCADE)
    # 与Author表建立多对多的关系,ManyToManyField可以建在两个模型中的任意一个,自动创建第三张表
    authors=models.ManyToManyField(to=‘Author‘,)
    def __str__(self):
        return self.title

原文地址:https://www.cnblogs.com/zhen1996/p/9822871.html

时间: 2024-12-11 16:45:10

10.20stark组件已经完工的相关文章

windows 10 服务组件安装出现0x80070422错误解决方法

问题描述: windows 10通过控制面板->程序->启用或关闭Windows 功能安装Windows服务或组件时,出现0x80070422错误,提示服务禁止或未启用 问题产生原因: 启用检测.下载和安装 Windows 和其他程序的更新.如果此服务被禁用,这台计算机的用户将无法使用 Windows 更新或其自动更新功能, 并且这些程序将无法使用 Windows 更新代理(WUA) API 问题解决方法: 启用Windows Update服务即可 原文地址:https://www.cnblo

Vuejs——(10)组件——父子组件通信

版权声明:出处http://blog.csdn.net/qq20004604 目录(?)[+] 本篇资料来于官方文档: http://cn.vuejs.org/guide/components.html#u7236_u5B50_u7EC4_u4EF6_u901A_u4FE1 本文是在官方文档的基础上,更加细致的说明,代码更多更全. 简单来说,更适合新手阅读 (二十七)父子组件通信 ①访问子组件.父组件.根组件: this.$parent    访问父组件 this.$children   访问子

推荐 11 款 React Native 开源移动 UI 组件

推荐 11 款 React Native 开源移动 UI 组件 oschina 发布于 10个月前,共有 14 条评论 本文推荐 11 个非常棒的 React Native 开源组件,希望能给移动应用开发者提供帮助. React Native 是近期 Facebook 基于 MIT 协议开源的原生移动应用开发框架,已经用于 Facebook 的生产环境.React Native 可以使用最近非常流行的 React.js 库来开发 iOS 和 Android 原生 APP. 1. iOS 表单处理

windows 10专业版14393.351 64位纯净无广告版系统 基于官方稳定版1607制作 更新于20161109

系统特点: 1.集成旧版Framework 3.5. 2.集成微软运行库(2005/2008/2013/2015). 3.集成正版压缩工具WinRAR 5.4. 4.去掉Edge浏览器,桌面显示IE浏览器,并且未锁定IE主页. 5.桌面干净,开始菜单简洁. 6.精简win 10无用组件.删除很多appx软件,仅保留计算器. 7.关闭自带防火墙windows defender. 8.转移pagefile.sys到D盘. 9.关闭休眠功能. 10.开启内置管理员批准模式. 11.任务栏时间添加星期显

React组件生命周期过程说明【转】

实例化 首次实例化 getDefaultProps getInitialState componentWillMount render componentDidMount 实例化完成后的更新 getInitialState componentWillMount render componentDidMount 存在期 组件已存在时的状态改变 componentWillReceiveProps shouldComponentUpdate componentWillUpdate render com

iOS开发之自定义表情键盘(组件封装与自动布局)

下面的东西是编写自定义的表情键盘,话不多说,开门见山吧!下面主要用到的知识有MVC, iOS开发中的自动布局,自定义组件的封装与使用,Block回调,CoreData的使用.有的小伙伴可能会问写一个自定义表情键盘肿么这么麻烦?下面将会介绍我们如何用上面提到的东西来定义我们的表情键盘的.下面的内容会比较多,这篇博文还是比较有料的. 还是那句话写技术博客是少不了代码的,下面会结合代码来回顾一下iOS的知识,本篇博文中用到的知识点在前面的博客中都能找到相应的内容,本篇算是一个小小的功能整合.先来张图看

在调试器里看Windows 10的Linux子系统

Windows 10是微软第三代NT团队的力挽狂澜之作,大刀阔斧地改造革新,目标是重塑Windows(Reinvent Windows)!在众多新特征中,Linux环境子系统(WSL)无疑是最具开创性和最拉风的一个. 启用WSL 在2016年3月30日开幕的Build大会上,微软向广大开发者宣布Windows 10将支持Linux应用.在2016年4月7号推送的 Windows 10 build 14328 fast ring中首次包含了WSL.在Windows 10的周年更新(Annivers

React组件生命周期过程说明

实例化 首次实例化 getDefaultProps getInitialState componentWillMount render componentDidMount 实例化完成后的更新 getInitialState componentWillMount render componentDidMount 存在期 组件已存在时的状态改变 componentWillReceiveProps shouldComponentUpdate componentWillUpdate render com

react组件生命周期过程

来自kiinlam github 实例化 首次实例化 getDefaultProps getInitialState componentWillMount render componentDidMount 实例化完成后的更新 getInitialState componentWillMount render componentDidMount 存在期 组件已存在时的状态改变 componentWillReceiveProps shouldComponentUpdate componentWill