上一主题 下一主题
ScriptCat,新一代的脚本管理器脚本站,与全世界分享你的用户脚本油猴脚本开发指南教程目录
12下一页
返回列表 发新帖

[油猴脚本开发指南]SweetAlert2进阶

[复制链接]
  • TA的每日心情
    无聊
    2022-4-18 01:37
  • 签到天数: 30 天

    [LV.5]常住居民I

    303

    主题

    2603

    帖子

    2666

    积分

    荣誉开发者

    非物质文化遗产社会摇传承人

    Rank: 10Rank: 10Rank: 10

    积分
    2666

    猫咪币纪念章

    发表于 2021-11-21 22:59:55 | 显示全部楼层 | 阅读模式

    前言

    我们之前已经学了SweetAlert2,这节课我们简单进行一下进阶的学习~

    对话框重用

    我们可以使用Swal.mixin来创建可重用的对话框

    const Toast = Swal.mixin({
      toast: true,
      position: 'top-end',
      showConfirmButton: false,
      timer: 3000,
      timerProgressBar: true,
      didOpen: (toast) => {
        toast.addEventListener('mouseenter', Swal.stopTimer)
        toast.addEventListener('mouseleave', Swal.resumeTimer)
      }
    })
    
    Toast.fire({
      icon: 'success',
      title: 'Signed in successfully'
    })

    模板声明

    我们也可以在html中写template模板然后在Swal传入来触发弹窗

    使用这种声明方式,在SSR情况下比较方便(本人未尝试)

    代码如下

    <template id="my-template">
      <swal-title>
        Save changes to "Untitled 1" before closing?
      </swal-title>
      <swal-icon type="warning" color="red"></swal-icon>
      <swal-button type="confirm">
        Save As
      </swal-button>
      <swal-button type="cancel">
        Cancel
      </swal-button>
      <swal-button type="deny">
        Close without Saving
      </swal-button>
      <swal-param name="allowEscapeKey" value="false" />
      <swal-param
        name="customClass"
        value='{ "popup": "my-popup" }' />
    </template>

    然后我们使用

    Swal.fire({
      template: '#my-template'
    })

    触发弹窗,其中template就是我们的template标签的id名

    支持的模板参数如下,因为这个感觉较为小众,所以我就没有尝试了

    <swal-title>...</swal-title>
    <swal-html>...</swal-html>
    <swal-footer>...</swal-footer>
    <swal-param name="..." value="..." />
    <swal-button type="..." color="..." aria-label="...">...</swal-button>
    <swal-image src="..." width="..." height="..." alt="..." />
    <swal-icon type="..." color="...">...</swal-icon>
    <swal-input type="..." label="..." placeholder="..." value="..." />
    <swal-input-option value="...">...</swal-input-option>

    声明式触发弹窗

    我们也可以在html中通过声明属性的方式,然后触发弹窗,这时候我们需要使用的命令是bindClickHandler方法

    例子如下

    <button data-swal-template="#my-template">
      Trigger modal
    </button>
    
    <button data-swal-toast-template="#my-template">
      Trigger toast
    </button>

    然后我们在js写

    Swal.bindClickHandler()
    
    Swal.mixin({
      toast: true,
    }).bindClickHandler('data-swal-toast-template')

    bindClickHandler如果不填写任何字符串,则默认为'data-swal-template'读取属性的字符串作为模板

    而如果传入了,则读取相应属性的模板

    这里我是通过源码大概看了一下才理解的,官方一笔带过,大家有兴趣也可以看一下,代码如下

    let bodyClickListenerAdded = false
    const clickHandlers = {}
    
    export function bindClickHandler (attr = 'data-swal-template') {
      clickHandlers[attr] = this
    
      if (!bodyClickListenerAdded) {
        document.body.addEventListener('click', bodyClickListener)
        bodyClickListenerAdded = true
      }
    }
    
    const bodyClickListener = (event) => {
      for (let el = event.target; el && el !== document; el = el.parentNode) {
        for (const attr in clickHandlers) {
          const template = el.getAttribute(attr)
          if (template) {
            clickHandlers[attr].fire({ template })
            return
          }
        }
      }
    }
    

    处理按钮的返回值

    当用户单击按钮的时候,Swal.fire返回的promise将返回一个SweetAlertResult对象

    键值如下

    isConfirmed:当确认按钮被点击,返回的result的这个属性将为true

    isDenied:当拒绝按钮被点击,返回的result的这个属性将为true,当弹窗有输入结果的时候,可以使用returnInputValueOnDeny: true返回输入的值

    isDismissed:当取消按钮被点击,返回的result的这个属性将为true,而dismiss属性将为Swal.DismissReason.cancel

    value:该值来源于窗口弹出,返回的result的这个属性有多种可能的值,当点击确认按钮时为true,拒绝为false,和存在输入框的时候为输入框的值

    dismiss:当点击取消按钮的时候存在该属性,为取消原因,关于取消原因可以查看接下来的内容

    取消原因

    当用户点击取消按钮的时候,Swal.fire将返回一个对象,包含了{ isDismissed: true,dismiss: reason },其中reason包含了取消的详细原因

    原因如下

    Swal.DismissReason.backdrop:点击了外部背景,相关配置为allowOutsideClick

    Swal.DismissReason.cancel:点击了取消按钮,相关配置为showCancelButton

    Swal.DismissReason.close:点击了关闭按钮,相关配置为showCloseButton

    Swal.DismissReason.esc:按了esc键,相关配置为allowEscapeKey

    Swal.DismissReason.timer:时间超时,对话框自动关闭,相关配置为timer

    如果使用了Swal.close关闭窗口,则Promise返回的obj中isDismissed:为true,但dismiss属性为undefined

    图标

    如下

    图片.png

    输入类型

    这里我们也可以限制对话框内的输入类型

    首先是text类型

    const ipAPI = '//api.ipify.org?format=json'
    
    const inputValue = fetch(ipAPI)
      .then(response => response.json())
      .then(data => data.ip)
    
    const { value: ipAddress } = await Swal.fire({
      title: 'Enter your IP address',
      input: 'text',
      inputLabel: 'Your IP address',
      inputValue: inputValue,
      showCancelButton: true,
      inputValidator: (value) => {
        if (!value) {
          return 'You need to write something!'
        }
      }
    })
    
    if (ipAddress) {
      Swal.fire(`Your IP address is ${ipAddress}`)
    }

    图片.png

    inputLabel是显示的文本

    inputValue是显示的值,如果是text,email,number,tel,textarea等类型,则可以传入一个promise值

    inputValidator对其进行合法性校验

    **const { value: ipAddress } = await Swal.fire**

    这里做了一个结构,对Swal.fire返回的promise做了一个await语法糖,同步等待返回对象,同时对对象进行解构拿到value的值,叫变量ipAddress

    并在最后显示出来。

    然后是email类型,代码如下

    const { value: email } = await Swal.fire({
      title: 'Input email address',
      input: 'email',
      inputLabel: 'Your email address',
      inputPlaceholder: 'Enter your email address'
    })
    
    if (email) {
      Swal.fire(`Entered email: ${email}`)
    }

    图片.png

    非常简单,不解释

    url类型

    const { value: url } = await Swal.fire({
      input: 'url',
      inputLabel: 'URL address',
      inputPlaceholder: 'Enter the URL'
    })
    
    if (url) {
      Swal.fire(`Entered URL: ${url}`)
    }

    图片.png

    password类型

    const { value: password } = await Swal.fire({
      title: 'Enter your password',
      input: 'password',
      inputLabel: 'Password',
      inputPlaceholder: 'Enter your password',
      inputAttributes: {
        maxlength: 10,
        autocapitalize: 'off',
        autocorrect: 'off'
      }
    })
    
    if (password) {
      Swal.fire(`Entered password: ${password}`)
    }

    图片.png

    maxlength最大长度

    autocapitalize取消首字母大写

    autocorrect关闭自动修正,这个可以百度一下看看

    textarea类型

    const { value: text } = await Swal.fire({
      input: 'textarea',
      inputLabel: 'Message',
      inputPlaceholder: 'Type your message here...',
      inputAttributes: {
        'aria-label': 'Type your message here'
      },
      showCancelButton: true
    })
    
    if (text) {
      Swal.fire(text)
    }

    inputAttributes添加到html对象的输入属性,其中键为属性名称,而值为添加的对应值

    select类型

    const { value: fruit } = await Swal.fire({
      title: 'Select field validation',
      input: 'select',
      inputOptions: {
        'Fruits': {
          apples: 'Apples',
          bananas: 'Bananas',
          grapes: 'Grapes',
          oranges: 'Oranges'
        },
        'Vegetables': {
          potato: 'Potato',
          broccoli: 'Broccoli',
          carrot: 'Carrot'
        },
        'icecream': 'Ice cream'
      },
      inputPlaceholder: 'Select a fruit',
      showCancelButton: true,
      inputValidator: (value) => {
        return new Promise((resolve) => {
          if (value === 'oranges') {
            resolve()
          } else {
            resolve('You need to select oranges :)')
          }
        })
      }
    })
    
    if (fruit) {
      Swal.fire(`You selected: ${fruit}`)
    }

    inputOptions为选项值

    图片.png

    radio类型

    /* inputOptions can be an object or Promise */
    const inputOptions = new Promise((resolve) => {
      setTimeout(() => {
        resolve({
          '#ff0000': 'Red',
          '#00ff00': 'Green',
          '#0000ff': 'Blue'
        })
      }, 1000)
    })
    
    const { value: color } = await Swal.fire({
      title: 'Select color',
      input: 'radio',
      inputOptions: inputOptions,
      inputValidator: (value) => {
        if (!value) {
          return 'You need to choose something!'
        }
      }
    })
    
    if (color) {
      Swal.fire({ html: `You selected: ${color}` })
    }

    这里他为了演示,返回了一个promise并设置一秒后结束promise

    返回的值是对象,其中键是对应的值,而属性则是名字

    图片.png

    checkbox类型

    const { value: accept } = await Swal.fire({
      title: 'Terms and conditions',
      input: 'checkbox',
      inputValue: 1,
      inputPlaceholder:
        'I agree with the terms and conditions',
      confirmButtonText:
        'Continue <i class="fa fa-arrow-right"></i>',
      inputValidator: (result) => {
        return !result && 'You need to agree with T&C'
      }
    })
    
    if (accept) {
      Swal.fire('You agreed with T&C :)')
    }

    设定了默认值以及单选框文本

    file类型

    const { value: file } = await Swal.fire({
      title: 'Select image',
      input: 'file',
      inputAttributes: {
        'accept': 'image/*',
        'aria-label': 'Upload your profile picture'
      }
    })
    
    if (file) {
      const reader = new FileReader()
      reader.onload = (e) => {
        Swal.fire({
          title: 'Your uploaded picture',
          imageUrl: e.target.result,
          imageAlt: 'The uploaded picture'
        })
      }
      reader.readAsDataURL(file)
    }

    这里没什么特别需要讲解的

    range类型

    Swal.fire({
      title: 'How old are you?',
      icon: 'question',
      input: 'range',
      inputLabel: 'Your age',
      inputAttributes: {
        min: 8,
        max: 120,
        step: 1
      },
      inputValue: 25
    })

    进度条类型,min为最小,max为最大,step为阶段提升值,inputValue为默认值

    提示

    不支持多个输入框输入

    但是可以通过html以及preConfirm属性来实现。

    在preConfirm你可以返回自定义结果,preConfirm可以接受一个promise

    例子如下

    const { value: formValues } = await Swal.fire({
      title: 'Multiple inputs',
      html:
        '<input id="swal-input1" class="swal2-input">' +
        '<input id="swal-input2" class="swal2-input">',
      focusConfirm: false,
      preConfirm: () => {
        return [
          document.getElementById('swal-input1').value,
          document.getElementById('swal-input2').value
        ]
      }
    })
    
    if (formValues) {
      Swal.fire(JSON.stringify(formValues))
    }

    主题

    sweetalert2有多种主题

    图片.png

    图片.png

    如何引入主题

    可以直接引入对应的css文件以及sweetalert2的js文件

    https://cdn.jsdelivr.net/npm/@sweetalert2/theme-dark@3/dark.css
    https://cdn.jsdelivr.net/npm/sweetalert2@9/dist/sweetalert2.min.js
    引入以上两个文件

    关于css文件地址

    你可以在

    https://cdn.jsdelivr.net/npm/@sweetalert2/themes@latest/

    找到对应的文件目录以及对应的css文件。

    结语

    拖了这么久终于给sweetalert2完结了...累死了

    图片.png
    混的人。
    ------------------------------------------
    進撃!永遠の帝国の破壊虎---李恒道
    个人宣言:この世界で私に胜てる人とコードはまだ生まれていません。死ぬのが怖くなければ来てください。
  • TA的每日心情
    无聊
    10 小时前
  • 签到天数: 30 天

    [LV.5]常住居民I

    15

    主题

    127

    帖子

    129

    积分

    荣誉开发者

    Rank: 10Rank: 10Rank: 10

    积分
    129

    国庆纪念章中秋纪念章

    发表于 2021-11-22 17:21:49 | 显示全部楼层
    ggnb!!!
    摸鱼中
    回复

    使用道具 举报

  • TA的每日心情
    无聊
    2022-4-18 01:37
  • 签到天数: 30 天

    [LV.5]常住居民I

    303

    主题

    2603

    帖子

    2666

    积分

    荣誉开发者

    非物质文化遗产社会摇传承人

    Rank: 10Rank: 10Rank: 10

    积分
    2666

    猫咪币纪念章

    发表于 2021-11-22 20:13:47 | 显示全部楼层

    呜呜呜
    现在没人看,越到后期看的人越少了
    混的人。
    ------------------------------------------
    進撃!永遠の帝国の破壊虎---李恒道
    个人宣言:この世界で私に胜てる人とコードはまだ生まれていません。死ぬのが怖くなければ来てください。
    回复

    使用道具 举报

    该用户从未签到

    1

    主题

    4

    帖子

    5

    积分

    助理工程师

    Rank: 1

    积分
    5
    发表于 2021-12-10 21:23:05 | 显示全部楼层
    李恒道 发表于 2021-11-22 20:13
    呜呜呜
    现在没人看,越到后期看的人越少了

    谢谢,不要气馁,好东西是会发光的。我在努力学习中。
    回复

    使用道具 举报

  • TA的每日心情
    无聊
    2022-4-18 01:37
  • 签到天数: 30 天

    [LV.5]常住居民I

    303

    主题

    2603

    帖子

    2666

    积分

    荣誉开发者

    非物质文化遗产社会摇传承人

    Rank: 10Rank: 10Rank: 10

    积分
    2666

    猫咪币纪念章

    发表于 2021-12-11 13:49:42 | 显示全部楼层
    shan869 发表于 2021-12-10 21:23
    谢谢,不要气馁,好东西是会发光的。我在努力学习中。

    谢谢哥哥,哥哥加油学
    混的人。
    ------------------------------------------
    進撃!永遠の帝国の破壊虎---李恒道
    个人宣言:この世界で私に胜てる人とコードはまだ生まれていません。死ぬのが怖くなければ来てください。
    回复

    使用道具 举报

    该用户从未签到

    1

    主题

    4

    帖子

    5

    积分

    助理工程师

    Rank: 1

    积分
    5
    发表于 2021-12-11 15:43:18 | 显示全部楼层
    李恒道 发表于 2021-12-11 13:49
    谢谢哥哥,哥哥加油学

    请教哥哥,VUE网页是不是不能用.val()赋值(这是QQ名为PIN 的一位哥哥说的,是论坛哪位哥哥?他好像也是很厉害的人物)?也有说是因为iframe框架不能获取元素(可控制台是能通过  document.querySelectorAll("input[placeholder='请输入']")[3].value='3324325'),
    类似这样直接赋值的。究竟vue应该用什么方法实现油猴直接输入文字?我自己看了很多文章都搞不定。可以搞一篇教程看看吗?谢谢
    回复

    使用道具 举报

  • TA的每日心情
    无聊
    2022-4-18 01:37
  • 签到天数: 30 天

    [LV.5]常住居民I

    303

    主题

    2603

    帖子

    2666

    积分

    荣誉开发者

    非物质文化遗产社会摇传承人

    Rank: 10Rank: 10Rank: 10

    积分
    2666

    猫咪币纪念章

    发表于 2021-12-11 17:30:11 | 显示全部楼层
    shan869 发表于 2021-12-11 15:43
    请教哥哥,VUE网页是不是不能用.val()赋值(这是QQ名为PIN 的一位哥哥说的,是论坛哪位哥哥?他好像也是很 ...

    vue是可以赋值的
    设置值之后根据https://bbs.tampermonkey.net.cn/thread-1250-1-1.html
    投递过去,即可设置值
    或者直接拿vm实例https://bbs.tampermonkey.net.cn/thread-1425-1-1.html
    混的人。
    ------------------------------------------
    進撃!永遠の帝国の破壊虎---李恒道
    个人宣言:この世界で私に胜てる人とコードはまだ生まれていません。死ぬのが怖くなければ来てください。
    回复

    使用道具 举报

    该用户从未签到

    1

    主题

    4

    帖子

    5

    积分

    助理工程师

    Rank: 1

    积分
    5
    发表于 2021-12-11 17:43:14 | 显示全部楼层
    李恒道 发表于 2021-12-11 17:30
    vue是可以赋值的
    设置值之后根据https://bbs.tampermonkey.net.cn/thread-1250-1-1.html
    投递过去,即可 ...

    谢谢,教程没看完,我看完不懂再请教。
    回复

    使用道具 举报

  • TA的每日心情
    无聊
    2022-4-18 01:37
  • 签到天数: 30 天

    [LV.5]常住居民I

    303

    主题

    2603

    帖子

    2666

    积分

    荣誉开发者

    非物质文化遗产社会摇传承人

    Rank: 10Rank: 10Rank: 10

    积分
    2666

    猫咪币纪念章

    发表于 2021-12-11 20:37:13 | 显示全部楼层
    shan869 发表于 2021-12-11 17:43
    谢谢,教程没看完,我看完不懂再请教。

    哥哥加油
    混的人。
    ------------------------------------------
    進撃!永遠の帝国の破壊虎---李恒道
    个人宣言:この世界で私に胜てる人とコードはまだ生まれていません。死ぬのが怖くなければ来てください。
    回复

    使用道具 举报

    该用户从未签到

    0

    主题

    2

    帖子

    3

    积分

    助理工程师

    Rank: 1

    积分
    3
    发表于 2022-1-14 01:28:27 | 显示全部楼层
    还会接着更新吗?等更新
    回复

    使用道具 举报

    发表回复

    本版积分规则

    快速回复 返回顶部 返回列表