精华内容
下载资源
问答
  • Command.TS重写 command.ts리라이트다버전입니
  • [RFC] 用 ts 重写

    2020-12-09 14:21:19
    <div><p>我用 ts 重写一遍?</p><p>该提问来源于开源项目:react-component/switch</p></div>
  • luogu冬日画板自动绘图脚本,使用TS重写了去年的脚本,支持多用户,维护
  • vue3.0+vite+ts 重写手机端upload组件

    千次阅读 多人点赞 2020-09-03 08:26:12
    重新运行yarn install 编写代码 Vue3.0-ts-upload **uploader组件 ** 不足之处 / 一些想法 props传参时,是否应使用如下代码: interface IProps{ title:string, limit:number, ... } props:[title,limit], setup...

    前言

    nice to meet you~ 认识一下

    大家好~ 很高兴在这里写下了自己的第一篇文章。

    github地址

    里面有关于这个组件的完整代码,还有一些todo、发布订阅、观察者等相关代码。

    移动端上传通用组件

    编写目的

    • 记录vue3.0尝鲜的开发过程

    • 一边体验Compositon API一边学习typescript

    关注组件

    通常开发一个组件,我们需要问自己两个问题:

    1、这个组件是解决什么问题?

    2、组件颗粒化需要达到什么程度?

    回答如下:

    1、提高复用性、提升开发效率、解耦等等。

    2、像上传组件,我们需要考虑自身项目及业务了,这里我这边的需求比较简单,大概是满足上传->预览/删除->数据回调即可。

    满足以下需求:

        - [x] 调用手机相机、相册
    
        - [x] 获取图片并渲染到浏览器
    
        - [x] 解决图片EXIF旋转
    
        - [x] 预览图片
    
        - [x] 删除图片
    
        - [x] 支持上传图片配置
    
        - [x] 支持多选
    
        回调方法:
    
        @on-change="onChange"
    
        @on-success="onSuccess"
    
        @on-error="onError"
    
    

    vue3.0、vite搭建

      $ yarn create vite-app <project-name>
    
      $ cd <project-name>
    
      $ yarn
    
      $ yarn dev
    
    

    集成 typescript

      $yarn add --dev typescript
    

    集成 sass

      $yarn add sass
    

    安装sass时,你会发现控制台报错,解决方法:

    1. 打开package.json

    2. 把dependencies里的sass这一行,移到devDependencies

    3. 重新运行yarn install

    编写代码

    <template>
      <div>
        <h1>Vue3.0-ts-upload</h1>
        <k-uploader
          :files="fileList"
          title="vue3.0_ts_组件上传"
          @on-change="onChange"
          @on-success="onSuccess"
          @on-error="onError"
        ></k-uploader>
      </div>
    </template>
    
    <script lang="ts">
    import { reactive, ref } from "vue";
    import KUploader from "../components/Uploader/Uploader.vue";
    
    // 附件对象接口
    interface IFile {
      url: string;
    }
    export default {
      components: {
        KUploader,
      },
      setup() {
        const activeId = ref<number | null>(null);
        // 默认附件数据
        const fileList = reactive<Array<IFile>>([
          {
            url: "https://ossweb-img.qq.com/images/lol/web201310/skin/big84000.jpg",
          },
          {
            url: "https://ossweb-img.qq.com/images/lol/web201310/skin/big37006.jpg",
          },
          {
            url: "https://ossweb-img.qq.com/images/lol/web201310/skin/big39000.jpg",
          },
        ]);
    
        const onSuccess = (res: IFile) => {
          console.log(res);
          console.log("success");
        };
        const onError = (res: IFile) => {
          console.log(res);
          console.log("error");
        };
        const onChange = (res: IFile[]) => {
          console.log(res);
          console.log("change");
        };
        return {
          fileList,
          activeId,
          onSuccess,
          onError,
          onChange,
        };
      },
    };
    </script>
    
    <style>
    </style>
    

    **uploader组件 **

    <script lang="ts">
    import { ref, reactive, watchEffect } from "vue";
    import { handleFile, transformCoordinate, dataURItoBlob } from "./utils";
    // 文件信息接口
    interface IFile {
      url: string;
    }
    interface IFileItem {
      url: string;
      blob: any;
    }
    // InputEvent接口
    interface HTMLInputEvent extends Event {
      target: HTMLInputElement & EventTarget;
    }
    export default {
      name: "Uploader",
      props: {
        title: {
          type: String,
          default: "图片上传",
        },
        files: {
          type: Array, //初始化数据源
          default: () => [],
        },
        limit: {
          type: Number, //限制上传图片个数
          default: 9,
        },
        capture: {
          type: Boolean, //是否只选择调用相机
          default: false,
        },
        enableCompress: {
          type: Boolean, //是否压缩
          default: true,
        },
        maxWidth: {
          type: Number, //图片压缩最大宽度
          default: 1024,
        },
        quality: {
          type: Number, //图片压缩率
          default: 0.9,
        },
        url: {
          type: String, //上传服务器url
          default: "",
        },
        params: {
          type: Object, //上传文件时携带的自定义参数
          default: () => {},
        },
        name: {
          type: String, //上传文件时FormData的Key,默认为file
          default: "file",
        },
        autoUpload: {
          type: Boolean, //是否自动开启上传
          default: true,
        },
        multiple: {
          type: Boolean, //是否支持多选, `false`为不支持
          default: "",
        },
        readonly: {
          type: Boolean, //只读模式(隐藏添加和删除按钮)
          default: false,
        },
      },
      setup(props, { emit }) {
        // 待上传文件
        let fileList = reactive<any[]>(props.files);
        //fileList = files;
        // 预览开关
        let previewVisible = ref<Boolean>(false);
        // 当前预览的图片序号
        let currentIndex = ref(0);
        // 定义当前预览图片img
        let currentImg = ref<string | null>("");
        let inputValue = ref<string | null>("");
    
        watchEffect(()=>{
          
        })
    
    
        // 文件变更操作
        const handleChange = (event: HTMLInputEvent): void => {
          const { enableCompress, maxWidth, quality, autoUpload } = props;
          const target = event.target || event.srcElement;
          const inputChangeFiles: [] | any = target.files;
          // console.log("files", inputChangeFiles);
          if (inputChangeFiles.length <= 0) {
            // 调用取消
            return;
          }
          const fileCount = fileList.length + inputChangeFiles.length;
          if (fileCount > props.limit) {
            alert(`不能上传超过${props.limit}张图片`);
            return;
          }
          // console.log("handleFile");
          // 执行操作
          Promise.all(
            Array.prototype.map.call(inputChangeFiles, (file) => {
              return handleFile(file, {
                maxWidth,
                quality,
                enableCompress,
              }).then((blob) => {
                const blobURL = URL.createObjectURL(blob);
                const fileItem: any = <IFileItem>{
                  url: blobURL,
                  blob,
                };
                for (let key in file) {
                  if (["slice", "webkitRelativePath"].indexOf(key) === -1) {
                    fileItem[key] = file[key];
                  }
                }
                if (autoUpload) {
                  uploadFile(blob, fileItem)
                    .then((result) => {
                      fileList.push(fileItem);
                      // 回调方法
                      // vue2.x写法 :this.$emit('on-change', fileList);
                      emit("on-change", fileList);
                      console.log("success");
                    })
                    .catch((e) => {
                      fileList.push(fileItem);
                    });
                } else {
                }
              });
            })
          ).then(() => {
            inputValue.value = "";
          });
        };
    
        // 上传文件
        const uploadFile = (blob: string, fileItem: any) => {
          return new Promise((resolve, reject) => {
            // 暂时resolve 模拟返回 正式使用请删掉
            const result = {
              status: 1,
              msg: "上传成功",
              data: {
                filename: "图片名字",
                url:
                  "https://ossweb-img.qq.com/images/lol/web201310/skin/big84000.jpg",
              },
            };
            resolve(result);
            emit("on-success", result);
            return;
    
            const me = this;
            const { url, params, name } = props;
            const formData = new FormData();
            const xhr = new XMLHttpRequest();
    
            formData.append(name, blob);
            if (params) {
              for (let key in params) {
                formData.append(key, params[key]);
              }
            }
            xhr.onreadystatechange = () => {
              if (xhr.readyState === 1) {
                if (localStorage.getItem("token")) {
                  const accessToken: any = localStorage.getItem("token");
                  xhr.setRequestHeader("Authorization", accessToken);
                }
              }
              if (xhr.readyState === 4) {
                if (xhr.status === 200) {
                  const result = JSON.parse(xhr.responseText);
                  // 回调父页面on-success
                  // vue2.x写法 this.$emit("on-success", result, fileItem);
                  emit("on-success", result, fileItem);
                  resolve(result);
                } else {
                  // 回调父页面on-error
                  // vue2.x写法 this.$emit("on-error", xhr);
                  emit("on-error", xhr);
                  reject(xhr);
                }
              }
            };
            xhr.upload.addEventListener(
              "progress",
              function (evt) {
                if (evt.lengthComputable) {
                  const precent = Math.ceil((evt.loaded / evt.total) * 100);
                  // 上传进度
                }
              },
              false
            );
            xhr.open("POST", url, true);
            xhr.send(formData);
          });
        };
    
        // 预览图片、删除图片
        const handleFileClick = (
          e: MouseEvent,
          item: IFile,
          index: number
        ): void => {
          showPreviewer();
          currentImg.value = item.url;
          currentIndex.value = index;
        };
    
        // 显示预览
        const showPreviewer = () => {
          previewVisible.value = true;
        };
    
        // 隐藏预览
        const handleHide = () => {
          previewVisible.value = false;
        };
    
        // 删除图片
        const handleDelete = () => {
          const delFn = () => {
            handleHide();
            fileList.splice(currentIndex.value, 1);
            emit("on-change", fileList);
          };
          delFn();
        };
    
        return {
          fileList,
          previewVisible,
          currentImg,
          inputValue,
          handleChange,
          handleFileClick,
          handleHide,
          handleDelete,
        };
      },
    };
    </script>
    

    不足之处 / 一些想法

    • props传参时,是否应使用如下代码:
    interface IProps{
            title:string,
            limit:number,
            ...
    }
    props:[title,limit],
    setup(props:IProps,context){
    }
    
    将 props 独立出来作为第一个参数,可以让 TypeScript 对 props 单独做类型推导,不会和上下文中的其他属性相混淆。这也使得 setup 、 render 和其他使用了 TSX 的函数式组件的签名保持一致。
    
    • composition api 提倡的是代码提取和重用逻辑,但我个人觉得我还没做到这点,以后要加强。

    写在最后

    • 感谢能花费自己宝贵的时间看完这篇文章的读者们。

    • 希望能一起在代码这条路上努力~

    最后别忘了点赞噢 谢谢~

    展开全文
  • 现在的前端真的看不懂啊,还有重学ES6 TypeScript , 还要安nodejs npm 编译 vue-next 状态:测试版。 1.所有计划中的RFC已合并。 2.... 3.Vue CLI现在通过vue-cli-plugin-vue-next提供了实验性支持。...

    现在的前端真的看不懂啊,还有重学ES6 TypeScript , 还要安nodejs npm 编译

    vue-next 状态:测试版。

    1.所有计划中的RFC已合并。
    2.所有合并的RFC已实现。
    3.Vue CLI现在通过vue-cli-plugin-vue-next提供了实验性支持。

    这里还有一个简单的基于webpack的简单安装程序,支持“单文件组件”。
    请注意,与2.x仍然可能存在未记录的行为不一致。
    遇到这种情况时,请确保首先检查现有RFC是否已经提出了行为差异。
    如果不一致不是RFC的一部分,则很可能是意料之外的,应该打开一个问题(打开新问题时请确保使用问题助手)。
    此外,当前的实现在运行时环境中需要本机ES2015 +,并且不支持IE11(尚未)。达到RC阶段后,将可以处理IE11兼容版本

     

    展开全文
  • TS Vue 重写 APlayer HTML5 音乐播放器
  • 这是TypeScript AST变形金刚,可让您相应地在输出JS& d.ts文件中重写导入路径。 这样做的主要用例是减轻不同的构建系统导入结构,例如相对import与绝对import以及别名化输出import路径。 用法 打字稿 ttypescript...
  • 我们分析内核源码可知,Ft5x06_ts触摸屏驱动程序涉及如下内容: 1. Linux下I2C驱动框架 2. Linux下中断系统 3. Linux下workqueue机制 4. Linux下输入子系统 5. 中断初始化、I2C控制器相关初始...

     我们分析内核源码可知,Ft5x06_ts触摸屏驱动程序涉及如下内容:

    1.  Linux下I2C驱动框架

    2.  Linux下中断系统

    3.  Linux下workqueue机制

    4.  Linux下输入子系统

    5.  中断初始化、I2C控制器相关初始化。在arch/arm/mach-exynos/mach-smdk4x12.c中的s3c_i2c1_set_platdata(&tiny4412_i2c1_data);

         

          Ft5x06_ts触摸屏驱动相关的源文件包括:  Ft5x06_ts.c、Ft5x06_ts.h、plat/ft5x0x_touch.h、Ts-if.c、Tiny4412_1wire_host.c(背光控制和一线精准触摸)等。

          内核中,Ft5x06_ts触摸屏驱动都被静态地编译进了内核,不方便调试,我们如何动态地加载此驱动呢,需要基于bus-dev-drv模型重新设计此驱动程序,步骤如下:


    1.  配置内核

    (1)去掉内核原有的驱动

    make  menuconfig后去掉 < >   FocalTech ft5x0x TouchScreen driver一项。

      Symbol: TOUCHSCREEN_FT5X0X_SINGLE [=n]                                                            |
     Type  : boolean                                                                                   |
      Prompt: Disable MULTI-Touch Mode                                                                  |
         Defined at drivers/input/touchscreen/Kconfig:327                                                |
         Depends on: !S390 && !UML && INPUT [=y] && INPUT_TOUCHSCREEN [=y] && TOUCHSCREEN_FT5X0X [=n]    |
         Location:                                                                                       |
           -> Device Drivers                                                                             |
             -> Input device support                                                                     |
               -> Generic input layer (needed for keyboard, mouse, ...) (INPUT [=y])                     |
                 -> Touchscreens (INPUT_TOUCHSCREEN [=y])                                                |
                   -> FocalTech ft5x0x TouchScreen driver (TOUCHSCREEN_FT5X0X [=n])


    (2)修改内核源码

          修改mach-Tiny4412.c中2215行,注释掉即可。

         //i2c_register_board_info(1, smdk4x12_i2c_devs1,ARRAY_SIZE(smdk4x12_i2c_devs1));

         如果配置内核时,去掉了一线触摸和ft05txx驱动,这里不用注释掉。


    2.  实现dev


    i2c_touchscreen_dev.c : 


    #include <linux/kernel.h>
    #include <linux/module.h>
    #include <linux/platform_device.h>
    #include <linux/i2c.h>
    #include <linux/err.h>
    #include <linux/regmap.h>
    #include <linux/slab.h>
    
    #include <linux/gpio.h>
    #include <mach/gpio.h>
    #include <plat/gpio-cfg.h>
    
    
    #include <plat/ft5x0x_touch.h>
    static struct ft5x0x_i2c_platform_data ft5x0x_pdata = {
    	.gpio_irq		= EXYNOS4_GPX1(6),//对应原理图中EINT14
    	.irq_cfg		= S3C_GPIO_SFN(0xf),
    	.screen_max_x	= 800,
    	.screen_max_y	= 1280,
    	.pressure_max	= 255,
    };
    
    //0x50表示I2C设备的地址,一般在	I2C设备芯片手册可以查到
    static struct i2c_board_info ft5x0x_info = {	
    	I2C_BOARD_INFO("ft5x0x_ts", (0x70 >> 1)),//这个名字要和drv程序中的id_table中名字要一样
    	.platform_data = &ft5x0x_pdata,
    };
    
    static struct i2c_client *ft5x0x_client;
    
    static int ft5x0x_dev_init(void)
    {
    	struct i2c_adapter *i2c_adap;
    /*1.触摸屏这个I2C设备挂接在了处理器的第一条总线上
      2.把这个总线号改为5,也能成功加载此驱动,原因在于i2c_new_device而不是i2c_new_probed_device方法
    */
    	int busNum = 1 ;
    	
    	printk("ft5x0x dev of bus-dev-drv module_init!\n");
    	
    	i2c_adap = i2c_get_adapter(busNum);//这里要实验的触摸屏是挂接在第1条I2C总线上的,所以这里的参数是1
    	if (!i2c_adap) {
    		pr_err("failed to get adapter i2c%d\n", busNum);
    		return -ENODEV;
    	}
    	
    	ft5x0x_client = i2c_new_device(i2c_adap, &ft5x0x_info);//设置和注册i2c_client结构体
    	if (!ft5x0x_client){
    		//pr_err("failed to register %s to i2c%d\n",ft5x0x_info.type, busNum);
    		pr_err("failed to register ft5x0x to i2c%d\n",busNum);
    		return -ENODEV;
    	}	
    	
    	i2c_put_adapter(i2c_adap);
    	
    	return 0;
    }
    
    static void ft5x0x_dev_exit(void)
    {
    	printk("ft5x0x dev of bus-dev-drv module_exit!\n");
    	i2c_unregister_device(ft5x0x_client);
    }
    
    
    module_init(ft5x0x_dev_init);
    module_exit(ft5x0x_dev_exit);
    MODULE_LICENSE("GPL");
    
    
    

    3.  实现drv


    i2c_touchscreen_drv.c :

    #include <linux/kernel.h>
    #include <linux/module.h>
    #include <linux/i2c.h>
    #include <linux/input.h>
    #include <linux/delay.h>
    #include <linux/slab.h>
    #include <linux/interrupt.h>
    #include <linux/irq.h>
    #include <linux/gpio.h>
    #include <linux/platform_device.h>
    #include <linux/err.h>
    
    #ifdef CONFIG_HAS_EARLYSUSPEND
    #include <linux/earlysuspend.h>
    #endif
    
    #include <mach/gpio.h>
    #include <plat/gpio-cfg.h>
    #include <plat/ctouch.h>
    #include <plat/ft5x0x_touch.h>
    
    #include "ft5x06_ts.h"
    
    #ifndef CONFIG_TOUCHSCREEN_FT5X0X_SINGLE
    #define CONFIG_FT5X0X_MULTITOUCH		1
    #endif
    
    #define TOUCH_MAX_X						0x700
    #define TOUCH_MAX_Y						0x400
    
    static int swap_xy = 0;
    static int scal_xy = 0;
    
    
    /*---------------------------------------------------------
     * Chip I/O operations
     */
    
    static struct i2c_client *this_client;
    
    static int ft5x0x_i2c_rxdata(char *rxdata, int length) 
    {
    	int ret;
    	struct i2c_msg msgs[] = {
    		{
    			.addr	= this_client->addr,
    			.flags	= 0,
    			.len	= 1,
    			.buf	= rxdata,
    		},
    		{
    			.addr	= this_client->addr,
    			.flags	= I2C_M_RD,
    			.len	= length,
    			.buf	= rxdata,
    		},
    	};
    
    	ret = i2c_transfer(this_client->adapter, msgs, 2);
    	if (ret < 0)
    		pr_err("%s: i2c read error: %d\n", __func__, ret);
    
    	return ret;
    }
    
    #if 0
    static int ft5x0x_i2c_txdata(char *txdata, int length) 
    {
    	int ret;
    	struct i2c_msg msg[] = {
    		{
    			.addr	= this_client->addr,
    			.flags	= 0,
    			.len	= length,
    			.buf	= txdata,
    		},
    	};
    
    	ret = i2c_transfer(this_client->adapter, msg, 1);
    	if (ret < 0)
    		pr_err("%s: i2c write error: %d\n", __func__, ret);
    
    	return ret;
    }
    
    static int ft5x0x_write_reg(u8 addr, u8 val) 
    {
    	u8 buf[4];
    	int ret;
    
    	buf[0] = addr;
    	buf[1] = val;
    	ret = ft5x0x_i2c_txdata(buf, 2);
    	if (ret < 0) {
    		pr_err("write 0x%02x to reg (0x%02x) failed, %d", addr, val, ret);
    		return -1;
    	}
    
    	return 0;
    }
    #endif
    
    static int ft5x0x_read_reg(u8 addr, u8 *pdata) 
    {
    	u8 buf[4] = { 0 };
    	struct i2c_msg msgs[] = {
    		{
    			.addr	= this_client->addr,
    			.flags	= 0,
    			.len	= 1,
    			.buf	= buf,
    		},
    		{
    			.addr	= this_client->addr,
    			.flags	= I2C_M_RD,
    			.len	= 1,
    			.buf	= buf,
    		},
    	};
    	int ret;
    
    	buf[0] = addr;
    
    	ret = i2c_transfer(this_client->adapter, msgs, 2);
    	if (ret < 0) {
    		pr_err("read reg (0x%02x) error, %d\n", addr, ret);
    	} else {
    		*pdata = buf[0];
    	}
    
    	return ret;
    }
    
    static int ft5x0x_read_fw_ver(unsigned char *val)
    {
    	int ret;
    
    	*val = 0xff;
    	ret = ft5x0x_read_reg(FT5X0X_REG_FIRMID, val);
    	if (*val == 0x06) {
    #if 0
    		swap_xy = 1;
    		scal_xy = 1;
    #endif
    	} else {
    		/* TODO: Add support for other version */
    	}
    
    	return ret;
    }
    
    
    /*---------------------------------------------------------
     * Touch core support
     */
    
    static void ft5x0x_ts_report(struct ft5x0x_ts_data *ts) 
    {
    	struct ft5x0x_event *event = &ts->event;
    	int x, y;
    	int i;
    
    #ifdef CONFIG_FT5X0X_MULTITOUCH
    	for (i = 0; i < event->touch_point; i++) {
    		if (swap_xy) {
    			x = event->y[i];
    			y = event->x[i];
    		} else {
    			x = event->x[i];
    			y = event->y[i];
    		}
    
    		if (scal_xy) {
    			x = (x * ts->screen_max_x) / TOUCH_MAX_X;
    			y = (y * ts->screen_max_y) / TOUCH_MAX_Y;
    		}
    
    		input_report_abs(ts->input_dev, ABS_MT_POSITION_X, x);
    		input_report_abs(ts->input_dev, ABS_MT_POSITION_Y, y);
    
    		input_report_abs(ts->input_dev, ABS_MT_PRESSURE, event->pressure);
    		input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, event->pressure);
    		input_report_abs(ts->input_dev, ABS_MT_TRACKING_ID, i);
    
    		input_mt_sync(ts->input_dev);
    	}
    #else
    	if (event->touch_point == 1) {
    		if (swap_xy) {
    			x = event->y[i];
    			y = event->x[i];
    		} else {
    			x = event->x[i];
    			y = event->y[i];
    		}
    
    		if (scal_xy) {
    			x = (x * ts->screen_max_x) / TOUCH_MAX_X;
    			y = (y * ts->screen_max_y) / TOUCH_MAX_Y;
    		}
    
    		input_report_abs(ts->input_dev, ABS_X, x);
    		input_report_abs(ts->input_dev, ABS_Y, y);
    		input_report_abs(ts->input_dev, ABS_PRESSURE, event->pressure);
    	}
    
    	input_report_key(ts->input_dev, BTN_TOUCH, 1);
    #endif
    
    	input_sync(ts->input_dev);
    }
    
    static void ft5x0x_ts_release(struct ft5x0x_ts_data *ts) 
    {
    #ifdef CONFIG_FT5X0X_MULTITOUCH
    #if 0
    	/* NOT needed for ICS */
    	input_report_abs(ts->input_dev, ABS_MT_TOUCH_MAJOR, 0);
    #endif
    	input_mt_sync(ts->input_dev);
    #else
    	input_report_abs(ts->input_dev, ABS_PRESSURE, 0);
    	input_report_key(ts->input_dev, BTN_TOUCH, 0);
    #endif
    
    	input_sync(ts->input_dev);
    }
    
    static int ft5x0x_read_data(struct ft5x0x_ts_data *ts) 
    {
    	struct ft5x0x_event *event = &ts->event;
    	u8 buf[32] = { 0 };
    	int ret;
    
    #ifdef CONFIG_FT5X0X_MULTITOUCH
    	ret = ft5x0x_i2c_rxdata(buf, 31);
    #else
    	ret = ft5x0x_i2c_rxdata(buf, 7);
    #endif
    	if (ret < 0) {
    		printk("%s: read touch data failed, %d\n", __func__, ret);
    		return ret;
    	}
    
    	memset(event, 0, sizeof(struct ft5x0x_event));
    
    	event->touch_point = buf[2] & 0x07;
    
    	if (!event->touch_point) {
    		ft5x0x_ts_release(ts);
    		return 1;
    	}
    
    #ifdef CONFIG_FT5X0X_MULTITOUCH
    	switch (event->touch_point) {
    		case 5:
    			event->x[4] = (s16)(buf[0x1b] & 0x0F)<<8 | (s16)buf[0x1c];
    			event->y[4] = (s16)(buf[0x1d] & 0x0F)<<8 | (s16)buf[0x1e];
    		case 4:
    			event->x[3] = (s16)(buf[0x15] & 0x0F)<<8 | (s16)buf[0x16];
    			event->y[3] = (s16)(buf[0x17] & 0x0F)<<8 | (s16)buf[0x18];
    		case 3:
    			event->x[2] = (s16)(buf[0x0f] & 0x0F)<<8 | (s16)buf[0x10];
    			event->y[2] = (s16)(buf[0x11] & 0x0F)<<8 | (s16)buf[0x12];
    		case 2:
    			event->x[1] = (s16)(buf[0x09] & 0x0F)<<8 | (s16)buf[0x0a];
    			event->y[1] = (s16)(buf[0x0b] & 0x0F)<<8 | (s16)buf[0x0c];
    		case 1:
    			event->x[0] = (s16)(buf[0x03] & 0x0F)<<8 | (s16)buf[0x04];
    			event->y[0] = (s16)(buf[0x05] & 0x0F)<<8 | (s16)buf[0x06];
    			break;
    		default:
    			printk("%s: invalid touch data, %d\n", __func__, event->touch_point);
    			return -1;
    	}
    #else
    	if (event->touch_point == 1) {
    		event->x[0] = (s16)(buf[0x03] & 0x0F)<<8 | (s16)buf[0x04];
    		event->y[0] = (s16)(buf[0x05] & 0x0F)<<8 | (s16)buf[0x06];
    	}
    #endif
    
    	event->pressure = 200;
    
    	return 0;
    }
    
    static void ft5x0x_ts_pen_irq_work(struct work_struct *work) {
    	struct ft5x0x_ts_data *ts = container_of(work, struct ft5x0x_ts_data, work);
    
    	if (!ft5x0x_read_data(ts)) {
    		ft5x0x_ts_report(ts);
    	}
    
    	enable_irq(this_client->irq);
    }
    
    static irqreturn_t ft5x0x_ts_interrupt(int irq, void *dev_id) {
    	struct ft5x0x_ts_data *ts = dev_id;
    
    	disable_irq_nosync(this_client->irq);
    
    	if (!work_pending(&ts->work)) {
    		queue_work(ts->queue, &ts->work);
    	}
    
    	return IRQ_HANDLED;
    }
    
    
    /*---------------------------------------------------------
     * I2C client driver functions
     */
    
    #ifdef CONFIG_HAS_EARLYSUSPEND
    static void ft5x0x_ts_suspend(struct early_suspend *handler)
    {
    #if 0
    	struct ft5x0x_ts_data *ts;
    
    	ts = container_of(handler, struct ft5x0x_ts_data, early_suspend);
    
    	disable_irq(this_client->irq);
    	cancel_work_sync(&ts->work);
    	flush_workqueue(ts->queue);
    
    	ft5x0x_set_reg(FT5X0X_REG_PMODE, PMODE_HIBERNATE);
    #endif
    
    	printk("ft5x0x_ts: suspended\n");
    }
    
    static void ft5x0x_ts_resume(struct early_suspend *handler)
    {
    #if 0
    	/* Wakeup: output_L --> 100ms --> output_H --> 100ms */
    	enable_irq(this_client->irq);
    #endif
    
    	printk("ft5x0x_ts: resumed\n");
    }
    #endif
    
    static int ft5x0x_ts_probe(struct i2c_client *client, const struct i2c_device_id *id)
    {
    	struct ft5x0x_i2c_platform_data *pdata;
    	struct ft5x0x_ts_data *ts;
    	struct input_dev *input_dev;
    	unsigned char val;
    	unsigned int ctp_id;
    	int err = -EINVAL;
    
    	printk("ft5x0x_ts_probe match OK!\n");
    	
    	
    	ctp_id = tiny4412_get_ctp();
    	if (ctp_id != CTP_FT5X06 && ctp_id != CTP_AUTO) {
    		return -ENODEV;
    	}
    
    	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
    		err = -ENODEV;
    		goto exit_check_functionality_failed;
    	}
    
    	ts = kzalloc(sizeof(*ts), GFP_KERNEL);
    	if (!ts) {
    		err = -ENOMEM;
    		goto exit_alloc_data_failed;
    	}
    
    	pdata = client->dev.platform_data;
    	if (!pdata) {
    		dev_err(&client->dev, "failed to get platform data\n");
    		goto exit_no_pdata;
    	}
    
    	ts->screen_max_x = pdata->screen_max_x;
    	ts->screen_max_y = pdata->screen_max_y;
    	ts->pressure_max = pdata->pressure_max;
    
    	ts->gpio_irq = pdata->gpio_irq;
    	if (ts->gpio_irq != -EINVAL) {
    		client->irq = gpio_to_irq(ts->gpio_irq);
    	} else {
    		goto exit_no_pdata;
    	}
    	if (pdata->irq_cfg) {
    		s3c_gpio_cfgpin(ts->gpio_irq, pdata->irq_cfg);
    		s3c_gpio_setpull(ts->gpio_irq, S3C_GPIO_PULL_NONE);
    	}
    
    	ts->gpio_wakeup = pdata->gpio_wakeup;
    	ts->gpio_reset = pdata->gpio_reset;
    
    	INIT_WORK(&ts->work, ft5x0x_ts_pen_irq_work);
    	this_client = client;
    	i2c_set_clientdata(client, ts);
    
    	ts->queue = create_singlethread_workqueue(dev_name(&client->dev));
    	if (!ts->queue) {
    		err = -ESRCH;
    		goto exit_create_singlethread;
    	}
    
    	input_dev = input_allocate_device();
    	if (!input_dev) {
    		err = -ENOMEM;
    		dev_err(&client->dev, "failed to allocate input device\n");
    		goto exit_input_dev_alloc_failed;
    	}
    
    	ts->input_dev = input_dev;
    
    	set_bit(EV_SYN, input_dev->evbit);
    	set_bit(EV_ABS, input_dev->evbit);
    	set_bit(EV_KEY, input_dev->evbit);
    
    #ifdef CONFIG_FT5X0X_MULTITOUCH
    	set_bit(ABS_MT_TRACKING_ID, input_dev->absbit);
    	set_bit(ABS_MT_TOUCH_MAJOR, input_dev->absbit);
    	set_bit(ABS_MT_WIDTH_MAJOR, input_dev->absbit);
    	set_bit(ABS_MT_POSITION_X, input_dev->absbit);
    	set_bit(ABS_MT_POSITION_Y, input_dev->absbit);
    
    	input_set_abs_params(input_dev, ABS_MT_POSITION_X, 0, ts->screen_max_x, 0, 0);
    	input_set_abs_params(input_dev, ABS_MT_POSITION_Y, 0, ts->screen_max_y, 0, 0);
    	input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, 0, ts->pressure_max, 0, 0);
    	input_set_abs_params(input_dev, ABS_MT_WIDTH_MAJOR, 0, 200, 0, 0);
    	input_set_abs_params(input_dev, ABS_MT_TRACKING_ID, 0, FT5X0X_PT_MAX, 0, 0);
    #else
    	set_bit(ABS_X, input_dev->absbit);
    	set_bit(ABS_Y, input_dev->absbit);
    	set_bit(ABS_PRESSURE, input_dev->absbit);
    	set_bit(BTN_TOUCH, input_dev->keybit);
    
    	input_set_abs_params(input_dev, ABS_X, 0, ts->screen_max_x, 0, 0);
    	input_set_abs_params(input_dev, ABS_Y, 0, ts->screen_max_y, 0, 0);
    	input_set_abs_params(input_dev, ABS_PRESSURE, 0, ts->pressure_max, 0 , 0);
    #endif
    
    	input_dev->name = FT5X0X_NAME;
    	input_dev->phys = "input(mt)";
    	input_dev->id.bustype = BUS_I2C;
    	input_dev->id.vendor = 0x12FA;
    	input_dev->id.product = 0x2143;
    	input_dev->id.version = 0x0100;
    
    	err = input_register_device(input_dev);
    	if (err) {
    		input_free_device(input_dev);
    		dev_err(&client->dev, "failed to register input device %s, %d\n",
    				dev_name(&client->dev), err);
    		goto exit_input_dev_alloc_failed;
    	}
    
    	msleep(3);
    	err = ft5x0x_read_fw_ver(&val);
    	if (err < 0) {
    		dev_err(&client->dev, "chip not found\n");
    		goto exit_irq_request_failed;
    	}
    
    	err = request_irq(client->irq, ft5x0x_ts_interrupt,
    			IRQ_TYPE_EDGE_FALLING /*IRQF_TRIGGER_FALLING*/, "ft5x0x_ts", ts);
    	if (err < 0) {
    		dev_err(&client->dev, "Request IRQ %d failed, %d\n", client->irq, err);
    		goto exit_irq_request_failed;
    	}
    
    	disable_irq(client->irq);
    
    	dev_info(&client->dev, "Firmware version 0x%02x\n", val);
    
    #ifdef CONFIG_HAS_EARLYSUSPEND
    	ts->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 1;
    	ts->early_suspend.suspend = ft5x0x_ts_suspend;
    	ts->early_suspend.resume = ft5x0x_ts_resume;
    	register_early_suspend(&ts->early_suspend);
    #endif
    
    	enable_irq(client->irq);
    
    	tiny4412_set_ctp(CTP_FT5X06);
    	dev_info(&client->dev, "FocalTech ft5x0x TouchScreen initialized\n");
    	return 0;
    
    exit_irq_request_failed:
    	input_unregister_device(input_dev);
    
    exit_input_dev_alloc_failed:
    	cancel_work_sync(&ts->work);
    	destroy_workqueue(ts->queue);
    
    exit_create_singlethread:
    	i2c_set_clientdata(client, NULL);
    
    exit_no_pdata:
    	kfree(ts);
    
    exit_alloc_data_failed:
    exit_check_functionality_failed:
    	dev_err(&client->dev, "probe ft5x0x TouchScreen failed, %d\n", err);
    
    	return err;
    }
    
    static int __devexit ft5x0x_ts_remove(struct i2c_client *client) 
    {
    	struct ft5x0x_ts_data *ts = i2c_get_clientdata(client);
    
    	printk("ft5x0x drv of bus-dev-drv at24cxx_remove!\n");
    	
    #ifdef CONFIG_HAS_EARLYSUSPEND
    	unregister_early_suspend(&ts->early_suspend);
    #endif
    
    	if (client->irq) {
    		free_irq(client->irq, ts);
    	}
    
    	cancel_work_sync(&ts->work);
    	destroy_workqueue(ts->queue);
    
    	i2c_set_clientdata(client, NULL);
    	input_unregister_device(ts->input_dev);
    	if (ts->input_dev)
    		kfree(ts->input_dev);
    
    	kfree(ts);
    
    	return 0;
    }
    
    //用到哪些就声明哪些内容,比如driver_data用不到,所以这里就写0
    static const struct i2c_device_id ft5x0x_ts_id[] = {
    	{ FT5X0X_NAME, 0 },
    	{ }
    };
    
    MODULE_DEVICE_TABLE(i2c, ft5x0x_ts_id);
    
    /* 1. 分配/设置i2c_driver */
    static struct i2c_driver ft5x0x_ts_driver = {
    	.probe		= ft5x0x_ts_probe,
    	.remove		= __devexit_p(ft5x0x_ts_remove),
    	.id_table	= ft5x0x_ts_id,
    	.driver	= {
    		.name	= FT5X0X_NAME,//在这里,这个名字并不重要,重要的是id_table里面的名字,所以这里可以随便起
    		.owner	= THIS_MODULE,
    	},
    };
    
    static int __init ft5x0x_ts_init(void)
    {
    	
    	int ret;
    	
    	printk("ft5x0x drv of bus-dev-drv module_init!\n");
    	
    	/* 2. 注册i2c_driver */
    	ret = i2c_add_driver(&ft5x0x_ts_driver);
    	if (ret != 0){
    		pr_err("Failed to register ft5x0x I2C driver: %d\n", ret);
    	}
    		
    	return ret;
    }
    
    static void __exit ft5x0x_ts_exit(void)
    {
    	printk("ft5x0x drv of bus-dev-drv module_exit!\n");
    	i2c_del_driver(&ft5x0x_ts_driver);
    }
    
    module_init(ft5x0x_ts_init);
    module_exit(ft5x0x_ts_exit);
    
    MODULE_AUTHOR("<wenfs@Focaltech-systems.com>");
    MODULE_DESCRIPTION("FocalTech ft5x0x TouchScreen driver");
    MODULE_LICENSE("GPL");
    

    4.  编译模块之Makefile


    Makefile:


    KERN_DIR = /home/samba/linuxKernel_ext4Fs_src/linux-3.5-2015-8
    
    all:
    	make -C $(KERN_DIR) M=`pwd` modules 
    
    clean:
    	make -C $(KERN_DIR) M=`pwd` modules clean
    	rm -rf modules.order
    
    obj-m	+= i2c_touchscreen_dev.o
    obj-m	+= i2c_touchscreen_drv.o
    

    5.  测试

        测试时加载模块后才运行QT程序。   

    展开全文
  • 所以挺有经验的,重写一个难度也不大,而且比较随心所欲,还可以随意加一些自己想要的东西 qwq 截图 说明:该播放器是基于 @DIYgod /APlayer 的布局和 样式 采用 TS + Vue 组件化重构的 演示: ...
        

    简介

    @DIYgod/APlayer 是一款简洁漂亮的 HTML5 音乐播放器 (〃ノωノ)
    在我第一次看到这款播放器颜值的时候让我眼前一亮,我非常崇拜那些能设计出好看界面的设计师 (* >ω<)

    但是在用过之后发现还是有不足的地方 这是我曾经提过的 Issues

    用了一段时间,很喜欢 APlayer 简洁的 UI,提一些其他可改进的建议:

    1.我认为有必要提供动态管理播放列表的 API
    (如果没有,在需要动态添加歌曲到列表时只能重新初始化)
    2.应该提供一个销毁播放器的 API
    3.歌词允许异步添加,通常获取歌词接口是单独的
    (现在必须等待歌词接口返回再初始化播放器,若歌词获取失败或时间过长会同时影响到播放音乐功能)

    关于第三条,APlayer 其实是支持异步歌词的但仅支持传入 .lrc 文件的地址
    如果是像网易云/QQ音乐那样返回的是 JSON 格式的那就不满足需求了

    为什么不提 PR 要重写呢?
    这个我想了一会,最终还是觉得组件化的方式开发更好一些(原 APlayer 用的是原生 JS 没有依赖别的库)
    而且因为我以前还在做后端的时候就自己写过音乐播放器(仿微博播放器,当时不会用 Git 源码已丢)
    所以挺有经验的,重写一个难度也不大,而且比较随心所欲,还可以随意加一些自己想要的东西 qwq

    截图

    说明:该播放器是基于 @DIYgod/APlayer 的布局和 样式 采用 TS + Vue 组件化重构的

    Demo

    演示:http://aplayer.quq.cat
    文档:http://aplayer.quq.cat/docs
    源码:https://github.com/MoeFE/vue-...
    NPM:https://www.npmjs.com/package...
    播放列表来自网易云歌单:http://music.163.com/#/playli...

    如果喜欢的话别忘了点一个 star 哟 (*ゝω・)
    欢迎提 IssuesPR (´・_・`)

    框架选型

    为了大家使用方便,我选择 Vue ,可以响应式控制播放器各个属性 并以插件的形式发布(详情请看 demo
    我这里为了方便大家能更好的调试,在生产环境下开启了 SourceMapdevtools
    如果您安装了 vue-devtools 可以打开调试器查看组件划分和各个组件的信息

    至于为什么选择用 TypeScript 本文就不做过多的解释了
    大家可以自行在网上找一下 TypeScriptJavaScript 的区别

    我只能告诉你:对于一个曾经使用 C# 的开发者来说这简直不能太爽啦 微软爸爸赛高 (* >ω<)

    最后推荐一款 TS + Vue 的脚手架模版:https://github.com/Toilal/vue...
    以后或将加入到官方模版中:https://github.com/vuejs-temp...

    TS + React 的脚手架可以用这个:https://github.com/wmonk/crea...

    拆分组件

    拿到布局样式后要做的第一件事情就是拆分组件
    @DIYgod/APlayer 的布局和 样式 复制过来
    确保样式没有问题后再将各个组件的布局和样式单独复制出来
    不懂设计的只好复制了 请允许我做一个悲伤的表情 (ಗ ‸ ಗ )

    拆分组件

    我将播放器拆分成了以下组件:

    组件名称 组件说明
    APlayer.ts 播放器容器组件
    Button.ts 按钮组件
    Picture.ts 歌曲图片组件
    Container.ts 右侧容器组件
    Info.ts 歌曲信息组件
    Lyric.ts 歌词面板组件
    Progress.ts 进度条组件
    Time.ts 播放时间组件
    Volume.ts 音量控制组件
    List.ts 播放列表组件
    Item.ts 播放列表项组件

    再来一张更清晰的图片吧:

    vue-devtools

    点击查看高清原图

    功能开发

    功能开发其实没有多少难度,HTML5 已经封装好了 HTMLAudioElement 元素
    我们就是用一下它的 API 和视图进行数据绑定和交互而已 看一下文档就好了

    不过这里会遇到一个小问题,那就是 Vue 不能监听到 Audio 对象的属性变化
    因为 Audio 对象其实就是 HTMLAudioElement 元素,Vue 是不能监听到元素属性变化的,所以我想了一个小办法

    定义了一个 Media 接口,里面定义了和 Audio 对象相同的属性,在 Audio 的事件中对 Media 的属性进行同步
    这样的话,就可以使用 Media 对象响应式获取 Audio 的属性值
    可以查看这一段代码:APlayer.ts#L326-L334

    我这里简单介绍一些比较常用的属性和方法吧

    名称 说明
    autoplay 是否自动播放 (在 Safari 中无效,可以自行在初始化音频后手动调用 play 方法)
    bufferd 获取已缓冲的进度(必须在 readeyState >= 3 之后获取,否则会抛异常)
    loop 是否循环播放音频(推荐根据当前播放模式自行实现该功能)
    preload 预加载选项,推荐使用 metadata,在未播放时仅获取音频的长度,而不要加载整个音频
    src 获取或设置音频的播放地址
    volume 获取或设置音频的音量(0~1)
    paused 获取当前音频是否已暂停
    currentTime 获取或设置当前音频的播放进度(单位:秒)
    duration 获取当前音频的长度(单位:秒)
    playbackRate 获取或设置当前音频的播放速度
    play () 播放音频
    pause () 暂停音频

    点击查看所有 Media 事件

    事实上 AudioVideo 对象差不多 都属于 Media
    所以如果你会开发音乐播放器那么也会开发视频播放器了

    这里重点说一下 timeupdate 事件,这个事件在音频播放时不断触发,这个可以说是最有用的事件了
    因为在播放过程中需要不断的重绘播放器的播放进度和已播放时间
    如果有歌词的话,还需要根据当前的播放时间去同步歌词

    如果没有或者不知道这个事件的话,你可能会使用 setInterval 代替
    使用 setInterval 的话,会有两个问题:
    1.重绘时间到底设置多少合适?太快了影响性能,太慢了页面不同步
    2.如果用户暂停播放了,需要清除定时器,开始播放又要初始化定时器,太麻烦
    (或者偷懒的话可以判断 pausedreturn ,那么需要不断的跑一个空定时器)

    LRC 歌词解析和同步

    可能做这个功能的时候是最好玩的吧 qwq
    因为在很久以前 千千静听那个年代 我无聊的时候就做一下 LRC 歌词
    所以对这个功能很敏感 尽量做到最好吧 (´・_・`)

    这里主要功能是歌词解析,歌词同步的话只要计算出与当前播放时间最匹配的项元素
    然后设置歌词面板的滚动条位置到当前元素的位置即可

    常见的时间标签有以下几种

    [mm:ss] 只有分和秒的时间标签
    [mm:ss:ms] 有分、秒、毫秒的时间标签
    [mm:ss.ms] 有分、秒、毫秒的时间标签的另一种格式
    [mm:ss:ms][mm:ss.ms] 多个时间标签共享这一句相同的歌词

    我的思路是:
    首先按照行将歌词文本分割成数组,再按行进行解析
    使用正则表达式匹配出该行的 分、秒、毫秒 和显示的歌词文本
    将 分、秒、毫秒 都转换成毫秒单位然后加起来与歌词文本关联后保存到数组中,最后需要按照时间正序排列
    那么 当前要显示的歌词 = 过滤数组中 时间 < 当前播放时间 后的最后一项

    private async parseLRC (): Promise<void> {
      if (!this.lrc || this.lrc === 'loading') return
      if (this.isURL(this.lrc)) { // 如果歌词是一个URL地址则请求该地址获得歌词文本
        const { data } = await Axios.get(this.lrc.toString())
        this.currentLRC = data
      } else this.currentLRC = this.lrc
    
      const reg = /\[(\d+):(\d+)[.|:](\d+)\](.+)/
      const regTime = /\[(\d+):(\d+)[.|:](\d+)\]/g
      const regCompatible = /\[(\d+):(\d+)]()(.+)/
      const regTimeCompatible = /\[(\d+):(\d+)]/g
      const regOffset = /\[offset:\s*(-{0,1}\d+)\]/
      const offsetMatch = this.lrc.match(regOffset)
      const offset = offsetMatch ? Number.parseInt(offsetMatch[1]) : 0
      this.LRC = []
    
      const matchAll = (line: string) => {
        let match = line.match(reg) || line.match(regCompatible)
        if (!match) return
        if (match.length !== 5) return
        const minutes = Number.parseInt(match[1]) || 0
        const seconds = Number.parseInt(match[2]) || 0
        const milliseconds = Number.parseInt(match[3]) || 0
        const time = (minutes * 60 * 1000 + seconds * 1000 + milliseconds) + offset
        const text = (match[4] as string).replace(regTime, '').replace(regTimeCompatible, '')
        if (!text) return // 优化:不要显示空行
        this.LRC.push({ time, text })
        matchAll(match[4]) // 递归匹配多个时间标签
      }
    
      this.currentLRC.replace(/\\n/g, '\n').split('\n').forEach(line => matchAll(line))
    
      // 歌词格式不支持
      if (this.LRC.length <= 0) this.LRC = [{ time: -1, text: '(・∀・*) 抱歉,该歌词格式不支持' }]
      else this.LRC.sort((a, b) => a.time - b.time)
    }

    点击查看完整代码

    总结

    完善了原 APlayer 不足的地方:
    1.可以响应式的随意控制播放器属性
    2.歌词同步支持多种时间标签格式(fix #39
    3.歌词同步兼容 [offset:0] 标签
    4.异步歌词的支持
    5.允许控制播放速度(相同的歌曲用不同的速度听感觉会不一样哦 quq)
    6.音量允许拖动控制
    7.支持注册所有 Media 事件
    8.保存播放器配置到 localStorage 中,刷新后可以恢复播放进度等信息

    并且体验了一把用 TSVue 的快感w

    最后 弱弱的:@MoeFE 欢迎各位大佬加入 (๑•̀ㅂ•́)و✧
    额..没啥要求 头像要萌要可爱的!!

    好想有个大佬能带我装逼带我飞 (ง •_•)ง

    展开全文
  • // 抽象类和重写重载继承多态 export {} // 抽象类.抽象方法不包括具体实现, 必须在子类里面实现; 抽象方法必须写在抽象类里面 abstract class Animal { //抽象类 name: string abstract speak():void //抽象...
  • js 的设计模式是经常使用的,但是最近在转 ts,所以就打算用 ts 重写 js 的设计模式. 说是重写其实也是模仿. 主要技术点: webpack + typescrpt + jest + ts-jest 使用 jest 测试的原因是使用和配置相对简单,并且...
  • :desktop_computer_selector: 介绍 荷马是一个“ Discord”机器人,提供任何好的机器人的基本功能:Google搜索,天气,任何您想要的信息。 而且,它是多语言的(当前为英语和法语)! 当然,它不止于此......
  • :desktop_computer_selector: 介绍 荷马是一个“ Discord”机器人,提供任何好的机器人的基本功能:Google搜索,天气,任何您想要的信息。 而且,它是多语言的(当前为英语和法语)! 当然,它不止于此......
  • 已打包并上传到npm @forzoom/shuttleTypescript正广泛成为前端工程师开发项目的首选,我手头上有一些使用js编写的Vue项目,最近准备使用ts重写。项目中单单是页面的数量就超过100个,更不用提组件的数量,如果对...
  • 类的继承 在使用TypeScript这门语言时,一个最重要基本功就是面向对象编程,那对类的扩展就变的格外重要,扩展经常使用的手段就是继承。 继承:允许我们创建一个类(子类),从已有的类(父类)上继承所有的属性和...
  • 全部用TS重写的(响应式、vdom、模本编译) 性能提升,减少代码量 会调整部分API Proxy重写响应式 vue2.x 马上要过时了吗 vue3.0从正式发布到推广,还需要一段时间 vue2.x应用范围广,有大量项目需要维护升级 proxy...
  • TS

    2021-01-05 17:21:53
    TSTS基础介绍TypeScript基础语法TypeScript程序由以下部分组成:tsc常用编译参数语法TypeScript和面向对象基础类型Any类型undefinedTypeScript变量声明类型断言变量作用域TypeScript运算符TypeScript条件语句...
  • 已打包并上传到npm @forzoom/shuttleTypescript正广泛成为前端工程师开发项目的首选,我手头上有一些使用js编写的Vue项目,最近准备使用ts重写。项目中单单是页面的数量就超过100个,更不用提组件的数量,如果对...
  • 重写toString方法

    2019-09-21 17:43:40
    当输出一个已重写toString方法的对象时(例如:System.out.println(ts);ts是一个实体类对象),输出代码会调用该对象的toString方法。即"System.out.println(ts);" = “ts.toString();” 举例如下: 首先定义一个...
  • 父类packagecom.yjm.Tes;publicabstractclassTs{protectedvoidTest(Stringstr,Strings){System.out.println("ts...");}}子类packagecom.yjm.Tes;publicclassTestextendsTs{protectedfinalvoidTest(St...
  • 父类packagecom.yjm.Tes;publicabstractclassTs{protectedvoidTest(Stringstr,Strings){System.out.println("ts...");}}子类packagecom.yjm.Tes;publicclassTestextendsTs{protectedfinalvoidTest(St...
  • 父类packagecom.yjm.Tes;publicabstractclassTs{protectedvoidTest(Stringstr,Strings){System.out.println("ts...");}}子类packagecom.yjm.Tes;publicclassTestextendsTs{protectedfinalvoidTest(St...
  • 父类packagecom.yjm.Tes;publicabstractclassTs{protectedvoidTest(Stringstr,Strings){System.out.println("ts...");}}子类packagecom.yjm.Tes;publicclassTestextendsTs{protectedfinalvoidTest(St...
  • Apache2.4重写

    2015-06-22 12:12:19
    <p>I have a UCP for my SAMP server, what worked fine with Apache2.2, but now we would like to move onto Ubuntu 14.04 with latest ...# vim: syntax=apache ts=4 sw=4 sts=4 sr noet </code></pre> </div>
  • java之重载和重写

    2020-08-12 18:00:33
    方法重载: 方法重载是指方法名和方法的返回类型都相同,但方法参数不一样. 参数不一样体现在参数个数、...Test ts = new Test() ; System.out.println(ts.ss(“s1”,“s2”)) ; System.out.println(ts.ss(“s1”)) ; } p
  • 更新[2019-5-9]更新[2019-5-10]AddedInitial release0、前言由于最近在重写个人的原生ts插件项目, 遇到了集成jest单测的需求, 单纯地使用ts-jest + ts-loader会出现难以估计的错误, 所以决定使用babel, 完美摒弃了...
  • 但拆分出了 <code>src/helper.ts、<code>src/nbnhhsh.ts、<code>src/app.ts</code> 等文件,以及把资源移动到了 <code>res/</code>,并且需要额外的构建步骤(tsc+webpack) 重写时 TypeScript 代码的...
  • /@Override public boolean equals(Object obj){ //当调用对象和参数指向同一个对象是,则内容一定相同 if (this == obj) return true; //当调用对象不为空而参数对象为空时,则内容一定不...Student ts = (Student) o
  • TypeScript在2018年势头迅猛,三大主流前端框架中,Angular和React开始就是使用TS编写的源码,而Vue3.0将使用TS重写,重写后的Vue3.0将更好的支持TS,届时三大框架都可以很好的支持开发者使用TS开发。而现在几乎所有...

空空如也

空空如也

1 2 3 4 5 ... 9
收藏数 177
精华内容 70
关键字:

ts重写