精华内容
下载资源
问答
  • vscode制作登录注册网页
    2022-07-13 00:46:46

    原文链接:编写一个VSCode插件

    自从使用过 VSCode 后就再也离不开 VSCode,其轻量的代码编辑器与诸多插件让多数开发者爱不释手。同样我也不例外,一年前的我甚至还特意买本《Visual Studio Code 权威指南》的书籍,来更进一步了解与使用。

    在购买这本书时就想写一个 vscode 插件(扩展),奈何当时事务繁忙加之不知做何功能,就迟迟未能动手。如今有时间了,就顺带体验下 vscode 插件开发,并记录整个开发过程。

    插件地址:VSCode-extension

    开源地址:kuizuo/vscode-extension (github.com)

    Vscode 相关

    vscode 应用商店

    vscode 插件官方文档

    vscode 官方插件例子

    关于 Vscode 及其插件就不过多介绍,相信这篇文章 VSCode 插件开发全攻略(一)概览 - 我是小茗同学 - 博客园 能告诉你 Vscode 插件的作用。

    工具准备

    :::tip

    在开发前,建议关闭所有功能性扩展,以防止部分日志输出与调试效率

    :::

    vscode 插件脚手架

    vscode 提供插件开发的脚手架 vscode-generator-code 来生成项目结构,选择要生成的类型

    ? ==========================================================================
    We're constantly looking for ways to make yo better!
    May we anonymously report usage statistics to improve the tool over time?
    More info: https://github.com/yeoman/insight & http://yeoman.io
    ========================================================================== Yes
    
         _-----_     ╭──────────────────────────╮
        |       |    │   Welcome to the Visual  │
        |--(o)--|    │   Studio Code Extension  │
       `---------´   │        generator!        │
        ( _´U`_ )    ╰──────────────────────────╯
        /___A___\   /
         |  ~  |
       __'.___.'__
     ´   `  |° ´ Y `
    
    ? What type of extension do you want to create? (Use arrow keys)
    > New Extension (TypeScript)
      New Extension (JavaScript)
      New Color Theme
      New Language Support
      New Code Snippets
      New Keymap
      New Extension Pack
      New Language Pack (Localization)
      New Web Extension (TypeScript)
      New Notebook Renderer (TypeScript)
    

    根据指示一步步选择,这里省略勾选过程,最终生成的项目结果如下

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nRDc3Le8-1657644399870)(https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/f2930db8192c4854996baf4da13d223b~tplv-k3u1fbpfcp-zoom-1.image)]

    运行 vscode 插件

    既然创建好了工程,那必然是要运行的。由于我这里选择的 ts + webpack 进行开发,所以是需要打包,同时脚手架已经生成好了对应.vscode 的设置。只需要按下 F5 即可开始调试,这时会打开一个新的 vscode 窗口,Ctrl+Shift+P打开命令行,输入Hello World,右下角弹出提示框Hello World from kuizuo-plugin!

    :::danger

    注意: 由于是 webpack 开发,在调用堆栈中可以看到有两个进程,一个是 webpack,另一个是新开的插件窗口的,同时在该调试窗口也能查看调试输出信息。

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7cvOpabv-1657644399880)(https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/e9554510d419439eb29c15b4e8f18a34~tplv-k3u1fbpfcp-zoom-1.image)]

    切记一定要等到第二个调试进程加载完毕(时间根据电脑性能而定),再打开命令行输入 Hello World 才会有命令,否则会提示 没有匹配命令。

    :::

    至此,一个 vscode 的开发环境就已经搭建完毕,接下来就是了解项目结构,以及 vscode 插件的 api 了。

    代码解读

    import * as vscode from 'vscode'
    
    export function activate(context: vscode.ExtensionContext) {
      let disposable = vscode.commands.registerCommand('kuizuo-plugin.helloWorld', () => {
        vscode.window.showInformationMessage('Hello World from kuizuo-plugin!')
      })
    
      context.subscriptions.push(disposable)
    }
    
    export function deactivate() {}
    

    vscode.commands.registerCommand用于注册命令,kuizuo-plugin.helloWorld 为命令 ID,在后续package.json中要与之匹配。第二个参数为一个回调函数,当触发该命令时,弹出提示框。

    在 package.json 中关注 activationEvents 与 contributes

    {
      "activationEvents": ["onCommand:kuizuo-plugin.helloWorld"],
      "contributes": {
        "commands": [
          {
            "command": "kuizuo-plugin.helloWorld",
            "title": "Hello World"
          }
        ]
      }
    }
    

    activationEvents 激活事件,onCommand:kuizuo-plugin.helloWorldkuizuo-plugin是插件 ID 要与 extension.ts 中的注册命令匹配,helloWorld则是命令标识,而 onCommand 则是监听的类型,此外还有onViewonUrionLanguage等等。

    contributes 则是配置那些地方来显示命令,像官方的例子中,就是在 Ctrl + Shift + P 命令行中输入 Hello World 来调用kuizuo-plugin.helloWorld 命令。此外还可以设置按键与菜单

    "keybindings": [
          {
            "command": "kuizuo-plugin.helloWorld",
            "key": "ctrl+f10",
            "mac": "cmd+f10",
            "when": "editorTextFocus"
          }
        ],
        "menus": {
          "editor/context": [
            {
              "when": "editorFocus",
              "command": "kuizuo-plugin.helloWorld",
              "group": "navigation"
            }
          ]
        }
    

    设置完毕后,可以按 Ctrl + Alt + O 或者命令行中键入 reload 来重启 vscode

    :::danger

    这里也要注意,如果重启后并无生效,请查看 package.json 是否配置正确(多一个逗号都不行),或者尝试重新调试。如果还不行,那么很有可能就是代码报错,但日志输出并没有,那么在弹出的新窗口中打开开发人员工具(Ctrl+Alt+I 或帮助 → 切换开发人员工具),这里有报错相关的提示信息。

    建议查看VSCode 插件开发全攻略(六)开发调试技巧

    :::

    功能

    首次启动弹窗与配置项

    先说首次启动弹窗的实现,要实现该功能,肯定要保证插件在 VSCode 一打开就运行,而这取决于 vscode 触发插件的时机,也就是 activationEvents,所以activationEvents需要设置成onStartupFinished。想要更高的优先级,可以选择 * (但官方不建议,除非其他事件无法实现的前提下),这里为了演示就使用*

    其实现代码主要调用 vscode.window.showInformationMessage 函数如下

    import * as vscode from 'vscode'
    import { exec } from 'child_process'
    
    export function activate(context: vscode.ExtensionContext) {
      vscode.window.showInformationMessage('是否要打开愧怍的小站?', '是', '否', '不再提示').then((result) => {
        if (result === '是') {
          exec(`start 'https://kuizuo.cn'`)
        } else if (result === '不再提示') {
          // 其他操作 后文会说
        }
      })
    }
    

    此时重启窗口,就会有如下弹窗显示

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pYFyjM60-1657644399882)(https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/85b2741822ea4af28f90984529baac94~tplv-k3u1fbpfcp-zoom-1.image)]

    但如果你是 mac 用户的话,你会发现无法打开,其原因是 window 下打开链接的指令是 start,而 mac 则是 open,所以需要区分不同的系统。要区分系统就可以使用 node 中的 os 模块的 platform 方法获取系统,如下(省略部分代码)

    import * as os from 'os'
    
    const commandLine = os.platform() === 'win32' ? `start https://kuizuo.cn` : `open https://kuizuo.cn`
    exec(commandLine)
    

    当然了,当用户选择不再提示的时候,下次再打开 vscode 就别提示了,不然大概率就是卸载插件了。这里就需要设置全局参数了,在 package.json 中 contributes 设置 configuration,具体如下,注意kuizuoPlugin.showTip 为全局参数之一

    "contributes": {
      "configuration": {
        "title": "kuizuo-plugin",
        "properties": {
          "kuizuoPlugin.showTip": {
            "type": "boolean",
            "default": true,
            "description": "是否在每次启动时显示欢迎提示!"
          }
        }
      }
    }
    

    该参数可以在设置 → 扩展中找到kuizuo-plugin插件来手动选择,也可以是通过 api 来修改

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6LzeGndg-1657644399884)(https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/813669faa6b546eda203abe9fdd214ec~tplv-k3u1fbpfcp-zoom-1.image)]

    然后读取vscode.workspace.getConfiguration().get(key)和设置该参数vscode.workspace.getConfiguration().update(key, value)

    export async function activate(context: vscode.ExtensionContext) {
      const key = 'kuizuoPlugin.showTip'
      const showTip = vscode.workspace.getConfiguration().get(key)
      if (showTip) {
        const result = await vscode.window.showInformationMessage('是否要打开愧怍的小站?', '是', '否', '不再提示')
        if (result === '是') {
          const commandLine = os.platform() === 'win32' ? `start https://kuizuo.cn` : `open https://kuizuo.cn`
          exec(commandLine)
        } else if (result === '不再提示') {
          //最后一个参数,为true时表示写入全局配置,为false或不传时则只写入工作区配置
          await vscode.workspace.getConfiguration().update(key, false, true)
        }
      }
    }
    

    即便是调试状态下,重启也不会影响全局参数。最终封装完整代码查看源码,这里不再做展示了。

    右键资源管理器(快捷键)新建测试文件

    我日常开发中写的最多的文件就是 js/ts 了,有时候就会在目录下创建 demo.js 来简单测试编写 js 代码,那么我就要点击资源管理器,然后右键新建文件,输入 demo.js。于是我想的是将该功能封装成快捷键的方式,当然右键也有新建测试文件这一选项。

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lmRxWWy0-1657644399885)(https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/eded811fae67413783b0a63572c4ccab~tplv-k3u1fbpfcp-zoom-1.image)]

    功能其实挺鸡肋的,也挺高不了多少效率,这里可以说为了演示和测试这个功能而实现

    总之前面这么多废话相当于铺垫了,具体还是看功能实现吧。

    首先就是注册命令,具体就不解读代码了,其逻辑就是获取调用vscode.window.showQuickPick弹出选择框选择 js 还是 ts 文件(自定义),接着获取到其目录,判断文件是否存在,创建文件等操作。

    import * as vscode from 'vscode'
    import * as fs from 'fs'
    
    export async function activate(context: vscode.ExtensionContext) {
      let disposable = vscode.commands.registerCommand('kuizuo-plugin.newFile', (uri: vscode.Uri) => {
        vscode.window.showQuickPick(['js', 'ts'], {}).then(async (item) => {
          if (!uri?.fsPath) {
            return
          }
    
          const filename = `${uri.fsPath}/demo.${item}`
          if (fs.existsSync(filename)) {
            vscode.window.showErrorMessage(`文件${filename}已存在`)
            return
          }
    
          fs.writeFile(filename, '', () => {
            vscode.window.showInformationMessage(`demo.${item}已创建`)
            vscode.window.showTextDocument(vscode.Uri.file(filename), {
              viewColumn: vscode.ViewColumn.Two, // 显示在第二个编辑器窗口
            })
          })
        })
      })
    
      context.subscriptions.push(disposable)
    }
    
    export function deactivate() {}
    

    然后再 keybindins 中添加一条

    "keybindings": [
      {
        "command": "kuizuo-plugin.newFile",
        "key": "shift+alt+n",
      }
    ],
    

    然后就当我实现完功能的时候,我在想自带的新建文件是不是就是个 command?只是没有绑定快捷键? 于是我到键盘快捷方式中找到答案

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xwhqLr9G-1657644399885)(https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/416e33d36f34427d8731eb525dfe0aa8~tplv-k3u1fbpfcp-zoom-1.image)]

    图中的explorer.newFile就是资源管理器右键新建文件的命令,只是没有键绑定。所以我只需要简单的加上shift + alt + n即可实现我一开始想要的快捷键功能,此时再次右键资源管理器新建文件右侧就有对应的快捷键。

    此时的我不知该哭该笑,折腾半天的功能其实只是设置个快捷键的事情。

    :::note

    这些命令在 vscode 中作为内置命令Built-in Commands。要查看 vscode 所有命令的话,也可以通过vscode.commands.getCommands 来获取所有命令 ID,要在插件中执行也只需要调用vscode.commands.executeCommand(id)

    :::

    键盘快捷键(光标移动)

    接着我就在想,既然很多 vscode 功能都是命令的形式,那是不是在插件级别就能做键盘映射,而不用让用户在 vscode 设置,很显然是可以的。只需要在 package.json 中 contributes 的 keybindings 中设置,就可以实现组合键来进行光标的移动。下面是我给出的答案

    "keybindings": [
          {
            "command": "cursorUp",
            "key": "shift+alt+i",
            "when": "textInputFocus"
          },
          {
            "command": "cursorDown",
            "key": "shift+alt+k",
            "when": "textInputFocus"
          },
          {
            "command": "cursorLeft",
            "key": "shift+alt+j",
            "when": "textInputFocus"
          },
          {
            "command": "cursorRight",
            "key": "shift+alt+l",
            "when": "textInputFocus"
          },
          {
            "command": "cursorHome",
            "key": "shift+alt+h",
            "when": "textInputFocus"
          },
          {
            "command": "cursorEnd",
            "key": "shift+alt+;",
            "when": "textInputFocus"
          }
        ]
    

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Cx7BFh5a-1657644399886)(https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/6674f9018ec94ecdadf2fd11326768eb~tplv-k3u1fbpfcp-zoom-1.image)]

    仔细看右侧来源就可以知道是没问题的,第一个为我之前设置的,而扩展则是通过上面的方法。

    自定义扩展工作台

    在 vscode 中有几个地方可以用于扩展,具体可看Extending Workbench | Visual Studio Code Extension API

    • 左侧图标(活动栏):主要有资源管理器、搜索、调试、源代码管理、插件

    • 编辑器右上角:代码分栏、code runner 的运行图标

    • 底部(状态栏):git、消息、编码等等

    在 contributes 添加 viewsContainers 与 views,注意,views 的属性要与 viewsContainers 的 id 对应。

    "viewsContainers": {
      "activitybar": [
        {
          "id": "demo",
          "title": "愧怍",
          "icon": "public/lollipop.svg"
        }
      ]
    },
    "views": {
      "demo": [
        {
          "id": "view1",
          "name": "视图1"
        },
        {
          "id": "view2",
          "name": "视图2"
        }
      ]
    }
    

    编辑器右上角是在 menus 中设置 editor/title,图标则是对应命令下设置,不然就是显示文字

    "commands": [
        {
          "command": "kuizuo-plugin.helloWorld",
          "title": "Hello World",
          "icon": {
            "light": "public/lollipop.svg",
            "dark": "public/lollipop.svg"
          }
        }
    ],
    "menus": {
        "editor/title": [
          {
            "when": "resourceLangId == javascript",
            "command": "kuizuo-plugin.helloWorld",
            "group": "navigation"
          }
        ],
    }
    

    至于底部状态栏,这里借用官方例子vscode-extension-samples/statusbar-sample at main · microsoft/vscode-extension-samples (github.com),最终效果如下

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HuPeeiRP-1657644399888)(https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/9655a221920742009e4a7a082a4edab5~tplv-k3u1fbpfcp-zoom-1.image)]

    那个 🍭 就是所添加的图标,不过并不实际功能,这里只是作为展示。

    自定义颜色、图标主题

    在 vscode 中分别有三部分的主题可以设置

    主题范围推荐
    文件图标主题资源管理器内的文件前的图标Material Icon Theme
    颜色主题代码编辑器以及整体颜色主题One Dark Pro
    产品图标主题左侧的图标Carbon Product Icons

    不过关于主题美化就不做深入研究,上面所推荐的就已经足够好看,个人目前也在使用。

    代码片段

    代码片段,也叫snippets,相信大家都不陌生,就是输入一个很简单的单词然后一回车带出来很多代码。平时大家也可以直接在 vscode 中创建属于自己的snippets

    代码片段相对比较简单,这里就简单跳过了

    xxx.log → console.log(xxx)包装

    功能描述:在一个变量后使用.log,即可转化为 console.log(变量)的形式就像 xxx.log => console.log('xxx', xxx) 有点像 idea 中的.sout

    这里我把 jaluik/dot-log 这个插件的实现逻辑给简化了,这里先给出基本雏形

    import * as vscode from 'vscode'
    
    class MyCompletionItemProvider implements vscode.CompletionItemProvider {
      constructor() {}
    
      // 提供代码提示的候选项
      public provideCompletionItems(document: vscode.TextDocument, position: vscode.Position) {
        const snippetCompletion = new vscode.CompletionItem('log', vscode.CompletionItemKind.Operator)
        snippetCompletion.documentation = new vscode.MarkdownString('quick console.log result')
    
        return [snippetCompletion]
      }
    
      // 光标选中当前自动补全item时触发动作
      public resolveCompletionItem(item: vscode.CompletionItem) {
        return null
      }
    }
    
    export function activate(context: vscode.ExtensionContext) {
      const disposable = vscode.languages.registerCompletionItemProvider(
        ['html', 'javascript', 'javascriptreact', 'typescript', 'typescriptreact', 'vue'],
        new MyCompletionItemProvider(),
        '.', // 注册代码建议提示,只有当按下“.”时才触发
      )
    
      context.subscriptions.push(disposable)
    }
    

    在 vscode 插件中通过vscode.languages.registerCompletionItemProvider提供像补全,代码提示等功能,第一个参数为所支持的语言,第二个参数为提供的服务vscode.CompletionItemProvider
    这里只是封装成类的形式,目的是为了保存一些属性,例如光标位置 position,也可以传递对象形式
    { provideCompletionItems, resolveCompletionItem } ,第三个参数则是触发的时机。

    provideCompletionItems
    需返回一个数组,成员类型为vscode.CompletionItem,可通过new vscode.CompletionItem()来创建。

    当你尝试运行上述代码时,会发现在任何值后面输入.都会有log提示。

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FXLCYHvD-1657644399889)(https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/277729d420c145f480f57b0c0d01221e~tplv-k3u1fbpfcp-zoom-1.image)]

    但是点击后只是满足了代码补全的功能,而选择 log 选项后所要执行的操作则是在 resolveCompletionItem 中实现,这里仅仅只是返回一个
    null,即只有简单的补全功能,这里对整个过程进行描述(可以自行下个断点调试查看):。

    1. 当输入.时,程序进入到provideCompletionItems
      函数内,这里可以获取到当前正在编辑的代码文档(文件名,代码内容)对应第一个参数,以及光标所在位置也就是第二个参数。还有其他参数,但这里用不到。具体可看CompletionItemProvider

    2. 选择完毕后,便会进入到 resolveCompletionItem 里面,这里可以获取到用户所选的选项内容,然后执行一系列的操作。

    要做代码替换的话就需要注册文本编辑命令vscode.commands.registerTextEditorCommand ,内容如下

    const commandId = 'kuizuo-plugin.log'
    const commandHandler = (editor: vscode.TextEditor, edit: vscode.TextEditorEdit, position: vscode.Position) => {
      const lineText = editor.document.lineAt(position.line).text
      // match case name.log etc.
      const matchVarReg = new RegExp(`\(\[^\\s\]*\[^\'\"\`\]\).${'log'}$`)
      // match case 'name'.log etc.  /(['"`])([^'"])\1.log/
      const matchStrReg = new RegExp(`\(\[\'\"\`\]\)\(\[^\'\"\`\]*\)\\1\.${'log'}$`)
      let matchFlag: 'var' | 'str' = 'var'
      let text,
        key,
        quote = "'",
        insertVal = ''
      ;[text, key] = lineText.match(matchVarReg) || []
      if (!key) {
        ;[text, quote, key] = lineText.match(matchStrReg) || []
        matchFlag = 'str'
      }
      // if matched
      if (key) {
        const index = lineText.indexOf(text)
        edit.delete(new vscode.Range(position.with(undefined, index), position.with(undefined, index + text.length)))
    
        if (matchFlag === 'var' && key.includes("'")) {
          quote = '"'
        }
        // format like console.log("xxx", xxx)
        if (matchFlag === 'var') {
          //  only console.log(xxx)
          insertVal = `${'console.log'}(${key})`
        }
        // if key is string format like console.log("xxx")
        if (matchFlag === 'str') {
          insertVal = `${'console.log'}(${quote}${key}${quote})`
        }
    
        edit.insert(position.with(undefined, index), insertVal)
      }
    
      return Promise.resolve([])
    }
    context.subscriptions.push(vscode.commands.registerTextEditorCommand(commandId, commandHandler))
    

    registerTextEditorCommand不同于registerCommand,它只针对编辑器的命令,例如可以删除代码中的某个片段,增加代码等等。上面的代码就是为了找到.log
    前(包括.log)匹配的代码,进行正则提取,然后调用 edit.delete 删除指定范围,再调用 edit.insert
    来插入要替换的代码,以此达到替换的效果。

    命令注册完毕了就需要调用了,也就到了 resolveCompletionItem 的时机

      public resolveCompletionItem(item: vscode.CompletionItem) {
        const label = item.label
        if (this.position && typeof label === 'string') {
          item.command = {
            command: 'kuizuo-plugin.log',
            title: 'refactor',
            arguments: [this.position.translate(0, label.length + 1)], // 这里可以传递参数给该命令
          }
        }
    
        return item
      }
    

    将命令赋值给 item.command,会自动调用其 command 命令,同时把 arguments 参数传入给 command。最终达到替换的效果。

    Position

    这里要说下 vscode 编辑器中的 Position,了解这个对代码替换、代码定位、代码高亮有很大帮助。

    position 有两个属性linecharacter,对应的也就是行号和列号(后文以linecharacter
    为称),**和**都是从 0 开始算起,而在 vscode 自带的状态栏提示中则是从 1 开始算起,这两者可别混淆了。

    其中 position 有如下几个方法

    position.translate

    根据当前坐标计算,例如当前 position 的 line 0,character1。position.translate(1, 1) 得到 line
    1,character 2,这不会改变远 position,这很好理解。但如果计算后得到的 line 与 character 有一个为负数则直接报错。

    position.with

    从自身创建一个新的 postion 对象

    Range

    知道了坐标信息,那么就可以获取范围了。可以通过 new vscode.Range() 来截取两个 position 之间的内容,得到的是一个 对象,有
    start 与 end 属性,分别是传入的两个 position。

    同样的 Range 和 Postion 方法都一致,这里就不多叙述了,可查看其声明文件。
    知道范围就可以通过 editor 来获取范围内的代码或是 edit 来删除代码等操作。

    知道了这些内容,再看上面的代码也不难理解了。

    选中变量并打印console.log

    这里在补充一个功能:选中一个变量的时候,按下快捷键在下方添加console.log(变量),相关插件 Turbo Console Log

    补:只有编辑器有光标的情况下会传入当前光标属性 position,选中状态下是不会传入 postion
    属性,而是要通过editor.selection来获取选中内容,是一个 Selection 对象。

    context.subscriptions.push(
      vscode.commands.registerTextEditorCommand(
        'kuizuo-plugin.insertLog',
        (editor: vscode.TextEditor, edit: vscode.TextEditorEdit) => {
          // 获取选中代码 在其下方插入 console.log(xxx)
          const { selection, selections } = editor
          // 选中多个代码时
          if (selections.length > 1) {
            return
          }
    
          // 如果不是当行代码
          if (!selection.isSingleLine) {
            return
          }
    
          const value = editor.document.getText(selection)
          const insertVal = `${os.EOL}${'console.log'}('${value}', ${value})`
    
          edit.insert(editor.selection.end, insertVal)
          editor.selection = new vscode.Selection(editor.selection.end, editor.selection.end) // 重置选中区域
          return Promise.resolve([])
        },
      ),
    )
    

    悬停提示

    这里也一笔带过,具体可看 hover.ts 中的代码。只要在 json 文件中,将鼠标悬停在kuizuo这个词中即可触发,试试看看。

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-upjrFjjS-1657644399890)(https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/624897f94d574101a4106e34e24f32a9~tplv-k3u1fbpfcp-zoom-1.image)]

    WebView

    使用 webView 可以在 vscode 内显示自定义的网页内容,丰富 vscode 功能,但所消耗的性能是肯定有的,就有可能影响 vscode
    的运行速度。官方给出的建议是:

    • 这个功能真的需要放在VSCode中吗?作为单独的应用程序或网站会不会更好呢?

    • webview 是实现这个功能的唯一方法吗?可以使用常规 VS Code API 吗?

    • 您的 webview 是否会带来足够的用户价值以证明其高资源成本?

    不过这里还只是作为一个演示,点击右上角的 logo 图标便可在 vscode 中打开网页。

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8ps5o3hE-1657644399891)(https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/087b28cab1ab4aad80246bbcbf3f9b23~tplv-k3u1fbpfcp-zoom-1.image)]

    不过要注意一点。新开的 webview 的背景是对应主题颜色的背景,如果网站有黑白模式的话,那么可能会导致颜色不对,故这里设置了 webview 的背景为白色。

    至于消息通信就不尝试了。

    发布

    大部分常用的 vscode 插件实现就此完毕,实际上有很多 api 还没尝试过,篇幅有限,就不一一列举了,后续若有开发实际作用插件再研究。具体可自行安装尝试一番,既然要让别人安装,这里就需要介绍发布了。

    这里在打包前重构下命令 ID,从 kuizuo-plugin → vscode-extension,同时把 package.json 的 name 改成了 vscode-extension-sample,因为发布的时候这个 id 必须唯一,不能与已有重名,到时候生成的为 kuizuo.vscode-extension-sample。(demo 给取了,不然我也不想起名为 sample)

    本地打包

    无论是本地打包还是发布到应用市场都需要借助vsce这个工具。

    安装

    npm i vsce -g
    

    打包成vsix文件:

    vsce package
    

    在打包时会提示一些信息,例如修改 README.md ,添加 LICENSE 等等,根据提示来操作即可。

    生成好的 vsix 文件不能直接拖入安装,只能从扩展的右上角选择Install from VSIX安装:

    发布到应用市场

    1、注册账号获取 token

    因为 Visual Studio Code 使用 Azure DevOps作为其 Marketplace 服务。所以需要登录一下Azure。登录后,如果之前没用过的话会要求创建一个组织,默认为邮箱前缀,这里如下点击

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hLVoC7zR-1657644399892)(https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/059487d8692b46b6a11091a89a047c64~tplv-k3u1fbpfcp-zoom-1.image)]

    2、新建一个 token

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5Dw4ttvi-1657644399892)(https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/0bfbe4b3803b424482fd554886f161db~tplv-k3u1fbpfcp-zoom-1.image)]

    根据图片选择,其中 Scopes 也可以选择:Full access,即所有权限。生成后会得到一个 token,保存它,当你关闭时便不再显示。

    3、创建一个发布者

    先使用网页版创建发布账号:https://marketplace.visualstudio.com/manage填写一些基本信息,然后在使用

    vsce login <publisher name>
    

    这里的 publisher name 根据 package.json 中的 publisher,会要求你输入 Personal Access Token,把刚刚创建的 token 的值粘贴过来即可

    提示
    The Personal Access Token verification succeeded for the publisher 'kuizuo'.
    就说明验证成功

    4、发布应用

    vsce publish
    

    :::warning
    这里要保证 package.json 的 name 在插件市场中唯一,否则会提示 The Extension Id already exist in the Marketplace. Please use the different Id。
    :::

    运行完毕后,最终提示Published kuizuo.vscode-extension-sample v1.0.0. 就说明发布完毕,发布和 npm 包一样,都无需审核,但要求包名唯一。

    可以在 Manage Extensions | Visual Studio Marketplace 中管理已发布的插件

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6960TERF-1657644399893)(https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/d61ca8af903b4ce39d0609ea0e0a81e2~tplv-k3u1fbpfcp-zoom-1.image)]

    这时在 vscode 扩展商店中搜索 vscode-extension-sample就能找到该插件VSCode-extension,也可以通过publisher:"kuizuo"来找到我的所有 vscode 插件。

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sHsUQcgj-1657644399894)(https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/5209a9b7fbbd404a9145e338ef33e0e1~tplv-k3u1fbpfcp-zoom-1.image)]

    总结

    整个开发过程的体验还是非常不错的,调试和代码提示都做得特别到位。不过有一点体验不好的,是大部分的配置信息都要写在 package.json 中,而在这里就不像 ts 那样有没有很好的代码提示了。不过当你填错命令 id 的时,vscode 还会提示命令 id 不存在,而不是不知道报错点。

    浅浅吐槽下:说真的 vscode 插件开发相关的文章与教程少之又少,有时候一个功能的一个 api 实现只能去查阅文档,而不像 chrome 插件,通过搜索引擎就能很快得出结果,而 vscode 插件往往得到的是推荐…但这也说明 chrome 插件开发的人远多于 vscode 插件,或者说远多于 IDE 插件的开发,也很正常,大部分编程好用的功能,已有大牛实现了对应的插件,多数开发者没有一些特别的需求完全就没必要接触 vscode 插件开发。就如我一年前就想写 vscode 插件,但却迟迟拖到现在,其原因可能就这。

    不过这类应用本就如此,就是不断翻阅文档,阅读前人的代码实现,再结合自身思路以完成最终目标。

    参考文章

    VSCode 插件开发全攻略(一)概览 - 我是小茗同学 - 博客园 (cnblogs.com)

    Extension API | Visual Studio Code Extension API

    更多相关内容
  • 本文给大家分享的是使用vscode编写的第一个html页面的全过程,非常的简单,菜鸟看看就行,高手请略过
  • 原生(HTML+CSS+JS),网页作品代码简单,可使用任意HTML编辑软件(如:`Dreamweaver、HBuilder、Vscode 、Sublime 、Webstorm、Text 、Notepad++` 等任意html编辑软件进行运行及修改编辑等操作) HTML5期末考核大作业...
  • 'myblog.apps.BlogConfig' #注册APP应用 ] 四 修改项目语言和时区 blogproject/blogproject/setting.py #修改语言 LANGUAGE_CODE = 'en-us' #修改前为英文 LANGUAGE_CODE = 'zh-hans' #修改后为中文 #修改时区 ...

    vscode+django 搭建自己的个人网站(三) ——创建应用以及基础配置

    前言

    ​ 创建好了数据库之后,接下来就要创建应用来开始创建自己的博客项目啦.

    ​ 但是创建过程中会需要大量的用到项目中的setting.py文件来进行各种相关配置,所以了解DJANGO的配置文件也是十分必要的.

    ​ 由于现在大家都在使用mysql数据库来做配置,但是DJANGO却自带了sqllite3数据库,而数据库的转换操作会比较麻烦,所以最后还会利用配置文件来提前修改数据库配置,便于我们后面的数据插入

    创建应用

    ​ 之前笔者创建的blogproject项目只是由DJANGO快速搭建的框架,目录下的文件都是可以自定义的配置文件,而正真创建我们自己的项目,就离不开创建自己的应用了

    ​ 在vscode中我们可以选中blogproject文件夹右键,选择在终端打开,这个时候只要输入下面的命令就能快速创建我们的APP项目了:

    python manage.py startapp APP项目名称
    

    注:这里要注意我们是在之前搭的的虚拟终端之中,所以用vscode下部的终端就好(这里笔者将应用起名为myblog)

    在这里插入图片描述

    当然,除了使用终端命令快速搭建以外,我们也可以选择手动来搭建自己需要的结构,应用的部分目录大概如下

    | --blogproject
    |	| --__init__.py
    |	| --asgi.py
    |	| --settings.py
    |	| --urls.py
    |	| --wsgi.py
    | --myblog
    |	| --__init__.py
    |	| --adimn.py
    |	| --apps.py
    |	| --models.py
    |	| --tests.py
    |	| --views.py
    | --manage.py
    

    创建成功后我们就可以开始自己博客的搭建之旅啦😄

    注:这里的blogproject/myblog与blogproject/blogproject文件是并列的不是包含关系,文件中的venv文件夹是虚拟环境所需文件,与项目无关

    基础配置

    前面说过我们会大量用到配置文件,并且我们在项目配置好后还需要对配置文件进行配置

    打开blogproject/blogproject下的setting.py文件.

    一 设置域名的访问权限

    blogproject/blogproject/setting.py
    ALLOWED_HOSTS = [] #修改前
    ALLOWED_HOSTS = ['*'] #修改后,表示任何域名都能访问
    

    二 设置模板路径

    设置TEMPLATES里的"DIRS",添加模板目录到templates的路径,后面用得着

    blogproject/blogproject/settings
    
    'DIRS': [], #修改前
    'DIRS': [os.path.join(BASE_DIR,'templates')], #修改后
    #这里使用pycharm的话会自动添加
    

    注:os模块需要导入,要在setting.py文件顶加入

    import os
    

    三 在INSTALLED_APPS添加APP应用名称

    blogproject/blogproject/setting.py
    
    INSTALLED_APPS = [
    		'django.contrib.admin',
    		...
    		'myblog.apps.BlogConfig' #注册APP应用
    ]
    

    四 修改项目语言和时区

    blogproject/blogproject/setting.py
    #修改语言
    LANGUAGE_CODE = 'en-us' #修改前为英文
    LANGUAGE_CODE = 'zh-hans' #修改后为中文
    #修改时区
    TIME_ZONE = 'UTC' #修改前
    TIME_ZONE = 'Asia/shanghai' #修改后
    

    点击调试后,利用浏览器登录网址就可以看见部分修改了的配置了,所用的setting.py中的提前配置主要是这些,下面还有比较主要的数据库的配置

    数据库配置mysql

    ​ 配置mysql数据库首先需要下载并安装配置mysql数据库,这里不做赘述,最好可以将mysql配置环境变量来方便我们的使用.

    ​ 在vscode中使用mysql需要使用扩展插件,在vscode左边栏中找到扩展,搜索mysql就有很多插件可以使用,这里笔者使用的是其中一款
    在这里插入图片描述

    使用也很方便,只要下载后重新打开vscode就能在左边栏找到插件,在里面进行连接就可以,这里的操作在插件就有介绍.

    ​ 提前利用终端创建数据库之后就可以在插件里连接并使用了,所有的数据库操作既可以在数据库,python mysqlclient模块操作,也可以在插件生成的sql文件中操作.

    ​ 接下来就要配置文件中修改配置了,在settings.py文件中找到

    DATABASE,修改如下:

    blogproject/blogproject/settings.py
    
    DATABASES = {	#修改后
        'default': {
            'ENGINE': 'django.db.backends.sqlite3',
            'NAME': os.path.join(BASE_DIR,'db.sqllite'),
        }
    }
    
    DATABASES = {	#修改后
        'default': {
            'ENGINE': 'django.db.backends.mysql',
            'NAME': 'blog',
            'USER':'root',
            'PASSWORD':'123456',
            'HOST':'localhost',
            'PORT':'3306'
        }
    }
    

    最后删去文件夹中的db文件

    修改之后就可以在项目里面使用mysql了,接下来只要按照前一篇的分析创建数据库就可以了.

    注:这里的数据库可能需要提前在终端创建再连接插件

    展开全文
  • 用户注册登录页面的设计与实现

    千次阅读 2021-06-13 14:17:48
    利用HTML5、CSS、JavaScript、jQuery以及mongodb数据库的相关知识,使用vscode编译器对Web应用程序的开发,主要实现了登录注册、首页部分功能 一、环境搭建 登录vscode官网下载安装Windows x64位的安装包 打开...


    前言

    利用HTML5、CSS、JavaScript、jQuery以及mongodb数据库的相关知识,使用vscode编译器对Web应用程序的开发,nodejs搭建本地服务器,主要实现了登录注册、首页部分功能


    一、环境搭建

    1. 登录vscode官网下载安装Windows x64位的安装包
    2. 打开下载的安装包进行安装,成功后运行,并安装所需要的插件如:汉化插件chinese等等。插件列表如下:
    插件名作用
    Auto Rename TagHTML修改标签时直接自动关联开始标签和结束标签,快速修改
    Beautify代码格式化,美化代码格式,例如换行、空格、缩进
    Auto Close Tag匹配标签,关闭对应的标签,即自动添加相对应的闭合标签
    open in browser用浏览器预览运行html文件
    1. Node下载安装

      1. 登录node官网下载安装包,安装方式有两种,一种是Windows安装包(.msi)形式,另一种是Windows(.exe)形式。
      2. 双击已下载好的安装包,点击Run(运行),勾选协议选项,点击next(下一步)按钮
      3. Node.js默认安装目录为"C:\Program Files\node js",这里可以修改目录,不推荐放在C盘,个人安装在F盘vscode下
      4. 测试系统环境变量,安装完成后,.msi格式的安装包已经将node.exe添加到系统环境变量path中,如果是以.zip 格式安装,因为没有安装过程,所以需要手动将node.exe所在目录添加到环境变量path 中,查看系统变量验证。
    2. Node配置环境变量

      1. 打开CMD,分别测试node和npm版本;输入node -v以及npm -v;显示版本号则环境变量配置成功,通常默认认Node.js安装完毕后,会自动在系统的path环境变量中配置了node.exe的目录 路径,但是由于机型设备不同,导致可能在安装完成后,dos命令输入node提示错误,不论是否成功,接下来我们手动设置系统变量和环境变量。
      2. 配置环境
        1. 在安装的文件夹【F:\vscode\nodejs】下创建两个 文件夹【node_global】及【node_cache】
        2. 创建完两个空文件夹之后,打开cmd命令窗口,输入npm config set prefix “F:\vscode\nodejs\node_global” npm config set cache “F:\vscode\nodejs\node_cache”
        3. 关闭cmd窗口,“我的电脑”-右键-“属性”-“高级系统设置”-“高级”-“环境变量”;①系统变量:进入环境变量对话框,在系统变量下新建NODE_PATH,输入 F:\vscode\nodejs\node_global\node_modules②用户变量:将用户变量下的Path后新增一个设置,用;将其和之前设置分隔开,即 F:\vscode\nodejs\node_global
      3. 测试
        1. 配置完后,安装个module模块测试下,安装个最常用的express模块,打开cmd窗口 使用npm安装个模块测试下,npm 安装 Node.js 模块语法格式如下:npm install <module name>
        2. 在安装时可以使用淘宝定制的 cnpm 命令行工具代替默认的 npm,首先需要下载淘宝镜像,如下npm install cnpm -g --registry=http://registry.npm.taobao.org;设置npm config set registry http://registry.npm.taobao.org;验证是否安装成功 安装完毕后检测cnpm是否安装成功,输入cnpm -v或者cnpm --version检测版本;查看当前镜像是否设置成功,把下面这个命令粘贴到 cmd 或终端上执行 npm get registry
        3. 设置缓存目录和日志目录存储位置;打开cmd输入npm config set prefix “F:\vscode\nodejs\node_global”
          和npmconfig set cache"F:\vscode\nodejs\node_cache"
      4. 安装插件
        1. 进入后端项目目录zjk-blog文件下输入cmd进入命令运行框,输入npm install安装相关插件
        2. 打开后端项目目录zjk-blog文件下输入cmd进去命令运行框,输入node app.js启动后端项目,显示项目端口为localhost:3000以及数据库服务相关内容则为成功运行服务器端
          在这里插入图片描述
    3. MongoDB环境配置(这里就不多叙述了)

      1. 3.x版本可见李子园的梦想博客
      2. 4.x版本可见SJ2050博客

    二、部分代码展示

    1.登录

    代码如下(示例):

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>登录页</title>
        <!-- 代码初始化,保证浏览器兼容,主流浏览器显示保持一致:chrome,FireFox,IE,Opera,safari -->
        <link rel="stylesheet" href="/public/css/base.css">
        <!-- 引入自定义样式表 -->
        <link rel="stylesheet" href="/public/css/login.css">
        <!-- 引入jquery库 -->
        <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
        <!-- 内部脚本 -->
    </head>
    <body>
        <!-- 登录页大盒子 -->
        <div class="login-box">
            <h1>账户登录</h1>
            <form>
                <!-- 账户 -->
                <div class="user-name">
                    <!-- 关联标签label和input的id保持一致 -->
                    <label for="name" class="iconfont iconzhanghao"></label>
                    <input id="name" type="text" placeholder="邮箱/用户名/登录手机">
                </div>
                <!-- 密码 -->
                <div class="user-pwd">
                    <!-- 关联标签label和input的id保持一致 -->
                    <label for="pwd" class="iconfont iconmima"></label>
                    <input id="pwd" type="password" placeholder="请输入密码">
                    <label class="iconfont iconclose-eye control_pwd"></label>
                </div>
                <!-- 注册按钮 -->
                <button class="submit-btn">登录</button>
                <!-- 相关操作 -->
                <div class="other-box">
                    <a href="#">忘记密码</a>
                    <a href="/register">立即注册</a>
                </div>
            </form>
        </div>
    </body>
    </html>
    

    2.注册

    代码如下(示例):

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>注册页</title>
        <!-- 代码初始化,保证浏览器兼容,主流浏览器显示保持一致:Chrome,FireFox,IE,Opera,Safari -->
        <link rel="stylesheet" href="/public/css/base.css">
        <!-- 引入自定义样式表 -->
        <link rel="stylesheet" href="/public/css/register.css">
        <!-- 引入jquery库 -->
        <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
    </head>
    <body>
        <!-- 注册大盒子 -->
        <div class="register-box">
            <h1>账户注册</h1>
            <!-- 表单 -->
            <form>
                <!-- 账户 -->
                <div class="user-name">
                    <!-- 关联标签label和input的id保持一致 -->
                    <label for="name" class="iconfont iconzhanghao"></label>
                    <input id="name" type="text" placeholder="请输入注册邮箱/用户名/手机">
                </div>
                <!-- 密码 -->
                <div class="user-pwd">
                    <!-- 关联标签label和input的id保持一致 -->
                    <label for="pwd" class="iconfont iconmima"></label>
                    <input id="pwd" type="password" placeholder="请输入密码">
                    <label class="iconfont iconclose-eye control_pwd"></label>
                </div>
                <!-- 确认密码 -->
                <div class="user-pwd-confirm">
                    <!-- 关联标签label和input的id保持一致 -->
                    <label for="pwd-confirm" class="iconfont iconquerenmima"></label>
                    <input id="pwd-confirm" type="password" placeholder="请再次输入密码">
                    <label class="iconfont iconclose-eye control_pwd"></label>
                </div>
                <!-- 性别 -->
                <div class="user-sex">
                    <!-- 关联标签label和input的id保持一致 -->
                    <label class="iconfont iconxingbie"></label><input type="radio" value="1" checked name="sex"><input type="radio" value="0" name="sex">
                </div>
                <!-- 注册按钮 -->
                <button class="submit-btn">注册</button>
                <!-- 相关操作 -->
                <div class="other-box">
                    <input id="agree" type="checkbox">
                    <label for="agree">已经阅读并同意</label>
                    <a href="#">相关协议</a>
                    <a href="/login">已有账号,点击登录</a>
                </div>
            </form>
        </div>
    </body>
    </html>
    

    2.login.css

    代码如下(示例):

    body{
        background-image: url('../imgs/bg.jpg');/*背景图的引入语法*/
        background-repeat: no-repeat;/*背景图的重复平铺-no-repeat表示不重复*/
        background-size: cover;/*背景图尺寸-cover全屏显示*/
        background-attachment: fixed;/*背景图粘贴固定-不随鼠标滚动进行移动*/
    }
    .login-box{
        width: 600px;/*宽度*/
        height: auto;/*高度-auto表示自动,由内容撑开*/
        border: 1px solid #fff;/*边框:粗细 形状 颜色*/
        margin: 200px auto;/*外边距-上下200,左右居中--块级元素水平居中*/
    }
    /* 后代选择器 语法:父元素 子元素 */
    .login-box h1{
        color: #fff;
        font-size: 30px;/*字体尺寸*/
        margin: 30px 0;/*上下边距30,左右为0*/
        text-align: center;/*字体水平居中--left、right、center、justfy两端对齐*/
    }
    form{
        width: 80%;
        margin: auto;
    }
    .user-pwd,
    .user-name{
        height: 60px;
        border: 1px solid #fff;
        border-radius: 26px;/*边框圆角*/
        margin-bottom: 25px;/*下边距--垂直方向距离下一个元素的距离*/
        display: flex;/*弹性盒模型*/
    }
    .user-pwd label,
    .user-name label{
        width: 60px;
        height: 60px;
        display: block;/*label标签默认为行级元素,无法直接设置宽高,因此display转为block块级元素*/
        line-height: 60px;/*行高--垂直方向居中-单元素设置*/
        text-align: center;/**/
        color: #fff;
        font-size: 30px;
    }
    .user-pwd input,
    .user-name input{
        flex: 1;/*表示占据剩余空间,避免了手动计算*/
        background-color: transparent;/*背景色透明*/
        /*
            去除边框
                border: none;
                border-width: 0px;
                border-style: none;
        */
        border-width: 0px;
        outline: none;/*外侧轮廓线*/
        color: #fff;
    }
    /*设置提示文本颜色*/
    .user-pwd input::-webkit-input-placeholder,
    .user-name input::-webkit-input-placeholder{
        color: #fff;
    }
    /*登录按钮样式*/
    .submit-btn{
        width: 100%;
        height: 60px;
        background: #fff;
        border: none;
        cursor: pointer;/*鼠标悬停变手*/
        border-radius: 26px;
        margin-bottom: 23px;
        columns: #555555;
        outline: none;/*去除轮廓线*/
    }
    .other-box{
        height: 60px;
        margin-bottom: 10px;
    }
    .other-box a{
        color: #555555;
    }
    /* 伪元素选择器last-child,表示选中最后一个a */
    .other-box a:last-child{
        float: right;
    }
    

    三、结果图

    登录
    在这里插入图片描述
    注册
    在这里插入图片描述
    主页
    在这里插入图片描述
    后台
    在这里插入图片描述

    展开全文
  • 制作一个网页,有登录界面、注册界面和个人相册界面,注册成功后在登录界面登录成功后进入个人相册界面,个人相册里的所有图片是顺时针旋转的。若失败返回登录界面,登录界面和注册界面可相互切换。 代码: login....

    制作一个网页,有登录界面、注册界面和个人相册界面,注册成功后在登录界面登录成功后进入个人相册界面,个人相册里的所有图片是顺时针旋转的。若失败返回登录界面,登录界面和注册界面可相互切换。
    代码:
    login.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>登录界面</title>
        <style>
            * {
                margin: 0;
                padding: 0;
            }     
            html {
                height: 100%;
                width: 100%;
                overflow: hidden;
                margin: 0;
                padding: 0;
                background: url(E:/source/material/images/c.jpg) no-repeat 0px 0px;
                background-repeat: no-repeat;
                background-size: 100% 100%;
                -moz-background-size: 100% 100%;
            }         
            body {
                display: flex;
                align-items: center;
                justify-content: center;
                height: 100%;
            }       
            #loginDiv {
                width: 40%;
                display: flex;
                justify-content: center;
                align-items: center;
                height: 300px;
                background-color: rgba(75, 81, 95, 0.3);
                box-shadow: 7px 7px 17px rgba(52, 56, 66, 0.5);
                border-radius: 5px;
            }         
            #name_trip {
                margin-left: 50px;
                color: red;
            }        
            p {
                margin-top: 30px;
                margin-left: 20px;
                color: rgb(2, 24, 24);
                font-size: 20px;
            }        
            input {
                margin-left: 0px;
                border-radius: 5px;
                border-style: hidden;
                height: 30px;
                width:300px;
                background-color: rgba(204, 180, 204, 0.5);
                outline: none;
                color: #0c0116;
                padding-left: 20px;
            } 
            .button {
                border-color: cornsilk;
                background-color: rgba(100, 149, 237, .7);
                color: aliceblue;
                border-style: hidden;
                border-radius: 5px;
                width: 100px;
                height: 31px;
                font-size: 16px;
                text-align: center;
            }
        </style>
    </head>
    <body>
        <div id="loginDiv">
            <div id="form">
                <h1 style="text-align: center;color: rgb(13, 13, 14);">立即登录</h1>
                <p style="text-align: center;">邮箱</p>
                <input type="text" placeholder="请输入邮箱" id="email"/>
                <p style="text-align: center;">密码</p>
                <input type="password" placeholder="密码长度至少为六位" id="passworld"/>
                </br></br>
                <a href="#" id="forget" style="text-align: center;">忘记密码?</a>
                </br>
                <div style="text-align: center;margin-top: 30px;">
                <button onclick="denlu()" class="button">登录</button>
                <button id="b2"onclick="click()" class="button">注册</button>
            </div>
            </div>
        </div>
    </body>
    <script language="javascript" type="text/javascript">
        document.getElementById("b2").onclick = function click(){
            window.location.href="register.html";
        }
        document.getElementById("forget").onclick = function click(){
          window.location.href="register.html";
        }
        email.onchange = function(){
    		var email = this.value;
    		var reg = /^([a-zA-Z]|[0-9])(\w|\-)+@[a-zA-Z0-9]+\.([a-zA-Z]{2,4})$/;
    		if(reg.test(email)){
    			//alert("邮箱格式正确"); 
    		}else{
    			alert("邮箱格式不正确");
    		}
    	}
        passworld.onchange = function(){
    		var passworld = this.value;
            var reg = /^(?![0-9]+$)(?![a-zA-Z]+$)[0-9A-Za-z]{6,12}$/;
    		if(reg.test(passworld)){
    		}else{
    			alert("密码格式不正确");
    		}
    	}
        function denlu() {
            var p = document.getElementById("passworld").value;
            var e = document.getElementById("email").value;
            var p2=localStorage.getItem("password");
            var e2=localStorage.getItem("email");
            if(p==p2&&e==e2)
                window.location.href="photo wall.html";
            else
                alert("账号或密码不正确");
        }
        </script>
    </html>
    

    register.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>注册界面</title>
        <style>
            body {
                margin: 0px;
                padding: 0px;
            }
            input {
                border-style:none none solid none;
                width: 50%;
                border-bottom: #000000 solid;
                font-size: 15px;
            }
            a {
                font-size: 60px;
                color:rgb(250, 201, 201);
            }
            p {
                font-size: 15px;
                font-weight:bold;
                color: rgb(0, 0, 0);
            }
            h1 {
                color: #fff;
            }
            h2 {
                position: relative;
                top: -73%;
                left:34%;
            }
            h5 {
                color: #fff;
            }
            button {    
                width: 200px;
                height: 30px;
                border-radius: 5%;
                background-color: #fcb928;    
                border: none;    
                color: rgb(10, 10, 10);     
                text-align: center;    
                text-decoration: none;    
                display: inline-block;    
                font-size: 12px;    
                margin: 4px 2px;    
                cursor: pointer;    
                -webkit-transition-duration: 0.4s;    
                transition-duration: 0.4s;}
                button:hover {    
                    box-shadow: 0 12px 16px 0 rgba(0,0,0,0.24),0 17px 50px 0 rgba(0,0,0,0.19);
                }
            #bg {
                background-image: url(E:/source/material/images/c.jpg);
                position:fixed;
                top: 0;
                left: 0;
                width:100%;
                height:100%;
                min-width: 1000px;
                z-index:-10;
                zoom: 1;
                background-color: #fff;
                background-repeat: no-repeat;
                background-size: cover;
                -webkit-background-size: cover;
                -o-background-size: cover;
                background-position: center 0;
            }
            #div1 {
    	    	margin:0 auto;
                position: relative;
                top:50px;
                width: 1006px;
                height: 563px;
                filter:alpha(opacity=50);
                opacity:0.5;
                background-color: rgb(255, 255, 255);
            }
            #left {
                float:left;
                width: 653px;
                height: 563px;
            }
            #right {
                text-align:center;
                float:left;
                width: 353px;
                height: 563px;
                background-image: url(E:/source/material/images/a.jpg);
            }
           #center {
               position: relative;
               top: 3%;
               left:3%;
               text-align:center;
               width: 581px;
               height: 471px;
           }
           .radio {
            margin: auto;
            width: 10%;
           }
        </style>
    </head>
    <body>
        <div id="bg">
            <div id="div1">
                <div id="left">
                    <div id="center">
                        </br>
                        <p>邮箱</p>
                        <input type="text" placeholder="请输入邮箱" id="email"/>
                        <p>用户名</p>
                        <input id="name" type="text" onchange="namechange()" placeholder="用户名长度不能超过5位"/>
                        <p>性别</p>
                        <p><input class="radio" type="radio" value="" name="people" checked="checked"><input class="radio" value="" type="radio" name="people"></p>
                        <p>头像</p>
                        <input type="file"/>
                        <p>密码</p>
                        <input id="passworld"type="password" placeholder="密码长度至少为6位,且为数字和字母的组合"/>
                        <p>确认密码</p>
                        <input id="ispassworld"type="password" placeholder="两次密码必须一致"/>
                        </br></br>
                        <button onclick="subm()">注册</button>
                    </div>
                </div>
                <div id="right">
                    <h1>已有帐号?
                        <h5>有账号就登录吧,好久不见了!
                        </br></br></br></br></br></br></br></br></br></br></br></br></br></br></br></br>
                    <button id="b2" onclick="click()">登录</button>
                </div>
            </div>
            <h2>立即注册
        </div>
    </body>
    <script language="javascript" type="text/javascript">
        document.getElementById("b2").onclick = function click(){
            window.location.href="login.html";
        }
        email.onchange = function(){
    		var email = this.value;
    		var reg = /^([a-zA-Z]|[0-9])(\w|\-)+@[a-zA-Z0-9]+\.([a-zA-Z]{2,4})$/;
    		if(reg.test(email)){
    		}else{
    			alert("邮箱格式不正确");
    		}
    	}
        function namechange(){
    		var x=document.getElementById("name").value.length;
    		if(x<=5){
    		}else{
    			alert("姓名格式不正确");
    		}
    	}
        passworld.onchange = function(){
    		var passworld = this.value;
            var reg = /^(?![0-9]+$)(?![a-zA-Z]+$)[0-9A-Za-z]{6,12}$/;
    		if(reg.test(passworld)){
    
    		}else{
    			alert("密码格式不正确");
    		}
    	}
        ispassworld.onchange = function(){
    		var p1 = this.value;
            var p2 = document.getElementById("passworld").value;
    		if(p2==p1){
    		}else{
    			alert("两次密码不相同");
    		}
    	}
        function subm() {
            var na = document.getElementById("name").value;
            var pword = document.getElementById("passworld").value;
            var emai = document.getElementById("email").value;
            localStorage.setItem("username",na);
            localStorage.setItem("password",pword);
            localStorage.setItem("email",emai);  
            window.location.href="login.html";
        }
    </script>
    </html>
    

    photo wall.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>照片墙</title>
        <style>
            body {
                margin: 0px;
            }
            #div1 {
                width: 100%;
                height: 50px;
                background: rgba(74, 105, 190, 0.966);
            }
            #div2 {
                background-image: url(E:/source/material/images/b.jpg);
                position:fixed;
                top: 0;
                left: 0;
                width:100%;
                height:100%;
                min-width: 1000px;
                z-index:-10;
                zoom: 1;
                background-color: #fff;
                background-repeat: no-repeat;
                background-size: cover;
                -webkit-background-size: cover;
                -o-background-size: cover;
                background-position: center 0;
            }
            #photo_box{
                width: 280px;
                height: 400px;
                position: fixed;
                left: 0;
                right: 0;
                top:0;
                bottom: 0;
                margin: 200px auto;
                transform-style: preserve-3d;/*表示所有子元素在3D空间中呈现*/
                transform: rotateX(-5deg) rotateY(0deg);
                animation: run 30s linear infinite;/*循环执行run动画,每30秒执行一次*/
            }
    
            /*设置图像大小、边框、圆角、位置*/
            #photo_box img{
                width: 250px;
                height: 350px;
                border: 5px solid #ccc;
                border-radius: 5px;
                position: absolute;
                left: 0;
                top: 0;
            }
    
            /*依次设置图像盒子中每个图像旋转后位置*/
            #photo_box img:nth-child(1){
                transform: rotateY(0deg) translateZ(500px);
            }
            #photo_box img:nth-child(2){
                transform: rotateY(36deg) translateZ(500px);
            }
            #photo_box img:nth-child(3){
                transform: rotateY(72deg) translateZ(500px);
            }
            #photo_box img:nth-child(4){
                transform: rotateY(108deg) translateZ(500px);
            }
            #photo_box img:nth-child(5){
                transform: rotateY(144deg) translateZ(500px);
            }
            #photo_box img:nth-child(6){
                transform: rotateY(180deg) translateZ(500px);
            }
            #photo_box img:nth-child(7){
                transform: rotateY(216deg) translateZ(500px);
            }
            #photo_box img:nth-child(8){
                transform: rotateY(252deg) translateZ(500px);
            }
            #photo_box img:nth-child(9){
                transform: rotateY(288deg) translateZ(500px);
            }
            #photo_box img:nth-child(10){
                transform: rotateY(324deg) translateZ(500px);
            }
            #photo_box img:nth-child(11){
                transform: rotateY(360deg) translateZ(500px);
            }
    
                /*采用@keyframes 规则创建run动画。*/
            @keyframes run {
                0%{transform: rotateX(0deg) rotateY(0deg);
                }
                25%{transform: rotateX(10deg) rotateY(90deg);
                }
                50%{transform: rotateX(0deg) rotateY(180deg);
                }
                75%{transform: rotateX(-10deg) rotateY(270deg);
                }
                100%{transform: rotateX(0deg) rotateY(360deg);
                }
            }
            #text1 {
                float: left;
                color:#fff;
                width: 150px;
                padding:12px 0;
                height: 50px;
            }
            #text2 {
                float: right;
                width: 100px;
                color:#fff;
                padding:12px 0;
                height: 50px;
            }
            #text3 {
                float: right;
                width: 100px;
                color:#fff;
                padding:12px 0;
                height: 50px;
            }
        </style>
    </head>
    <body>
        <div id="div1">
            <div id="text1">欢迎登录!</div>
            <div id="text2" onclick="outclick()" >退出</div>
            <div id="text3">个人信息</div>
        </div>
        <div id="div2">
            <div id="photo_box">
                <img src="E:/source/material/images/a1.jpg">
                <img src="E:/source/material/images/a2.jpg">
                <img src="E:/source/material/images/a3.jpg">
                <img src="E:/source/material/images/a4.png">
                <img src="E:/source/material/images/a5.jpg">
                <img src="E:/source/material/images/a6.jpg">
                <img src="E:/source/material/images/a7.jpg">
                <img src="E:/source/material/images/a8.jpg">
                <img src="E:/source/material/images/a9.jpg">
                <img src="E:/source/material/images/a10.jpg">
                <img src="E:/source/material/images/a11.jpg">
            </div>
        </div>
    </body>
    <script>
        var name=localStorage.getItem("username");
        var div1=document.getElementById("text1");
        div1.innerHTML="欢迎"+name+"登录!";
        function outclick() {
            localStorage.clear();
            window.location.href="login.html";
        }
    </script>
    </html>
    

    效果展示
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    展开全文
  • 看b站大佬现场演示,菜鸟的我尽量写的,然后那个jQuery文件我用的b站大佬,不用文件实现不了动态 效果图如下:
  • bootstrap实现登录注册界面

    万次阅读 2018-10-17 15:36:49
    注册功能编写完成,进行登录功能的编写,在function login(){ $.ajax() }中,与注册界面相同,同样要注意异步async要设置成false。    相应login.ashx代码:   登录界面运行结果:    
  • 1网页简介此作品为学生个人主页网页设计题材,HTML+CSS布局制作,web前端期末大作业,大学生网页设计作业源码,这是一个不错的网页制作,画面精明,代码为简单学生水平,非常适合初学者学习使用。2.网页编辑等任意html...
  • vscodevscode插件学习(三)

    千次阅读 2020-12-08 18:55:46
    今天继续学习制作vscode插件 本地读取文件 本次制作本地看小说插件。 就是本地txt文件在vscode里看小说。 贡献点 我们要在左侧出现个图标,这里我直接整了个reactapp的logo弄来。 当点击图标后激活命令,在左侧...
  • 校园网页设计 、学校班级网页制作、学校官网、小说书籍、等网站的设计与制作。️HTML静态网页设计作业使用dreamweaver制作,采用DIV+CSS布局,共有多个页面,首页使用CSS排版比较丰富,色彩鲜明有活力。顶部导航及...
  • 1 网页简介:此作品为学生个人主页网页设计题材,HTML+CSS 布局制作,web前端期末大作业,大学生网页设计作业源码,这是一个不错的网页制作,画面精明,代码为简单学生水平, 非常适合初学者学习使用。2.网页编辑:网页...
  • 校园网页设计 、学校班级网页制作、学校官网、小说书籍、等网站的设计与制作。️HTML静态网页设计作业使用dreamweaver制作,采用DIV+CSS布局,共有多个页面,首页使用CSS排版比较丰富,色彩鲜明有活力。顶部导航及...
  • HTML期末大作业~制作个人图片资源网页5个页面(HTML+CSS+JavaScript) 临近期末, 你还在为HTML网页设计结课作业,老师的作业要求感到头大?HTML网页作业无从下手?网页要求的总数量太多?没有合适的模板?等等一系列...
  • 旅游景点介绍、旅游风景区、家乡介绍、等网站的设计与制作。旅游景点介绍、旅游风景区是一个介绍简介、行政区划、地理环境、自然环境、教育事业、体育事业、旅游景点、城市荣誉等等。网站集中主要展示了的地方风土...
  • 背景作为一位前端同学肯定对...本次将讲述插件基本原理并从一个简单的case了解如何制作一个的vscode插件是什么实现了vscodeElectronvscode底层通过electron开发实现,electron的核心构成分别是:chromium、nodej...
  • dreamweaver网页设计作业制作 学生个人网页单页 WEB静态网页作业模板 大学生个人主页博客网页代码 dw个人网页作业成品 一、作品介绍 1.作品简介 :html期末大作业,dw学生网页设计作业, A+水平 ,喜欢的可以下载,文章...
  • HTML-第六周-表单-登录页面与跳转注册页面(代码在最后)
  • 校园班级网页设计 、‍我的班级网页、我的学校、‍校园社团、校园运动会、等网站的设计与制作。️HTML我的班级网页设计,采用DIV+CSS布局,共有多个页面,排版整洁,内容丰富,主题鲜明,首页使用CSS排版比较丰富,...
  • HTML期末大作业~ 学生HTML个人网页作业作品下载-个人主页博客网页设计制作 大学生个人网站作业模板 简单个人网页制作 临近期末, 你还在为HTML网页设计结课作业,老师的作业要求感到头大?HTML网页作业无从下手?网页...
  • 我们通过浏览器访问这些服务器上的网页。不同的网页通过超链接联系在一起,构成了WWW的网状结构。 2.HTML是表示网页的一种规范,它通过标记符定义了网页内容的显示,并使用属性进一步控制内容的显示。 3.Web标准...
  • ⭐个人网页设计网站模板采用DIV CSS布局制作网页作品有多个页面,如 :个人介绍(文字页面)、我的作品(图片列表)、个人技能(图文页面)、在线留言(表单页面)CSS样式方面网页整体采用左右布局结构,制作网页...
  • 一个简单的HTML网页(千与千寻电影) 大二学生网页设计与制作 电影主题网页制作学生个人网页设计作品 学生个人网页模板 简单个人主页成品 个人网页制作 HTML学生个人网站作业设计代做
  • 1 网页简介:此作品为学生个人主页网页设计题材,HTML+CSS 布局制作,web前端期末大作业,大学生网页设计作业源码,这是一个不错的网页制作,画面精明,代码为简单学生水平, 非常适合初学者学习使用。2.网页编辑:网页...
  • 适中 Atom GitHub 是 适中 WebStorm JetBrains 否 非常强大 HBuilder DCloud 是 非常强大 为什么现在不用 Dreamweaver 了 Dreamweaver 是曾经网页制作的王牌IDE,推崇 "所见即所得" ,用拖拽控件的方式进行网页...
  • 使用php开发动态网页,实现注册登录以及网页留言功能。 软件:wampserver、vscode wampserver集成了Apache Web服务器,MySQL数据库和PHP,提供虚拟服务器环境,vscode用于代码编辑。 最终效果: 二.环境...
  • 大学生影视主题网页制作 电影网页设计模板 学生静态网页作业成品 dreamweaver电影HTML网站制作

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 2,072
精华内容 828
关键字:

vscode制作登录注册网页