GVKun编程网logo

Ant Design Vue中TreeSelect详解(ant design vue tree)

18

在这里,我们将给大家分享关于AntDesignVue中TreeSelect详解的知识,让您更了解antdesignvuetree的本质,同时也会涉及到如何更有效地2019Electron+Vue+An

在这里,我们将给大家分享关于Ant Design Vue中TreeSelect详解的知识,让您更了解ant design vue tree的本质,同时也会涉及到如何更有效地2019Electron+Vue+Ant Design Vue仿网易云音乐windows客户端实战分享、Ant Design Mobile Ant Design Mobile Ant Design 移动端设计规范的 React 实现、Ant Design of Vue select框获取key和name的问题、ant design of vue 中的select问题的内容。

本文目录一览:

Ant Design Vue中TreeSelect详解(ant design vue tree)

Ant Design Vue中TreeSelect详解(ant design vue tree)

<template>
  <a-tree-select
    v-model:value="value":tree-data="treeData"
    allow-clear
    @select="selectHnader"
    search-placeholder="Please select"
  />
</template>
<script lang="ts">
import { TreeSelect } from 'ant-design-vue';
import { defineComponent,ref,toRefs,watch } from 'vue';

const treeData = [
  {
    title: '部门0-0',value: '0-0',key: '0-0',children: [
      {
        title: '部门0-0-0',value: '0-0-0',key: '0-0-0',},],{
    title: '部门0-1',value: '0-1',key: '0-1',children: [
      {
        title: '部门0-1-0',value: '0-1-0',key: '0-1-0',disabled: true,// 该值不能够选中
      },{
        title: '教育局',value: '0-1-1',key: '0-1-1',]
export default defineComponent({
  setup() {
    //   那么它将选中部门 部门0-0-0;
    // 通过value值显示对应的title值
    const value = ref(['0-0-0']);

    // 监听,但是可能不需要
    watch(value,() => {
      console.log(value.value);
    });

    function selectHnader(value:any,node:any,extray:any){
        console.log("==>value",value); //获取的是数据源中的value值
        console.log("==>node",toRefs(node) ); // 该选中节点的属性
        console.log("==>extray",extray.selectednodes[0].props.title); //得到显示的值
    }
    return {
      value,treeData,selectHnader
    };
  },});
</script>

使用select事件

select 事件 被选中时调用 
function(value,node,extra)
我使用 select事件主要是得到选中的显示值
最初我还想通过递归根据id得到显示的值{哈哈。尴尬了}

2019Electron+Vue+Ant Design Vue仿网易云音乐windows客户端实战分享

2019Electron+Vue+Ant Design Vue仿网易云音乐windows客户端实战分享

特点

  • 视频播放器
  • 拖拽播放
  • 桌面歌词
  • mini模式
  • 自定义托盘右键菜单
  • 任务栏缩略图,歌曲操作
  • 音频可视化
  • 自动/手动检查更新
  • Nedb数据库持久化
  • 自定义安装路径,安装界面美化
  • 浏览器中启动客户端
  • Travis CL,AppVeyor自动构建
  • 换肤,下载,本地歌曲匹配,网络变化桌面通知,分享歌曲/歌单/MV/视频等到QQ空间
  • 登录,私人Fm,歌单,专辑,歌手,排行榜,MV,视频,评论,搜索,用户,动态,粉丝,关注,云盘,收藏...
  • 心动模式,歌词微调,下一首播放,追加播放,单曲循环,随机播放,列表循环
  • 路由导向,局部刷新,首页栏目调整并持久化...
  • ...

下载 && 运行

项目地址

点击下载应用。

macOS用户请下载dmg文件,windows用户请下载exe文件,linux用户请下载AppImage文件。

项目当前依赖NeteaseCloudMusicApi,感谢NeteaseCloudMusicApi的作者。

当前只为windows做了适配 。

基于draggabilly封装一个可拖动的对话框

拖动对话框的身影在项目中还是挺常见的,如首页中的栏目调整对话框,收藏歌单等。

然而Ant Design Vue提供的对话框组件并没有提供拖拽的功能,但这一功能在项目中又是不可缺少的,所以只好自己动手丰衣足食。

封装一个drop-modal主要分三步:
  • 让drop-modal拥有拥有a-modal的API
  • 在drop-modal上实现v-model
  • modal首次显示后实例化Draggabilly

$attrs,$slots,$listeners

实现前两步的目的在于让书写drop-modal的语法和a-modal保持基本一致,其中第一步较为简单,新建drop-modal,其模板如下:

<template>
  <a-modal
    v-bind="{...$attrs,...$slots}"
    v-on="$listeners"
  >
    <slot></slot>
  </a-modal>
</template>

实现v-model

通常我们在a-modal上通过v-model绑定一个值,通过修改该值来控制对话框的显示隐藏,就像这样

<a-modal v-model="visible">
  <p>contents</p>
</a-modal>

所以我们也应该在drop-modal实现上实现v-model。如果了解自定义组件的v-model是:value和@input的语法糖,实现起来也不难。

  • 首先定义一个props value
  • 为了保持单向数据流,再定义一个计算属性 currentValue,在其get方法中返回value,在set方法中触发自定义事件
  • 最后将currentValue绑定在a-modal上即可。

核心代码如下:

<a-modal ... v-model="currentValue">
   ...
</a-modal>

computed: {
    currentValue: {
      get () {
        return this.value
      },
      set (val) {
        this.$emit(''input'', val)
      }
    }
}

实例化Draggabilly

最后一步也是最重要的一步,通过watch监听 value ,当值为true时实例一个Draggabilly让modal变成可拖动。这一步需要注意4点:

  1. 确保在nextTick中实例化Draggabilly
  2. 仅在首次显示时实例化Draggabilly
  3. 确定可拖动的dom
  4. modal的嵌套情况

至此封装的drop-modal满足当前项目的所有需求,当然也有不足。

总结

封装drop-modal所涉及的vue核心知识点——$attrs$slots$listeners,自定义组件的v-model的还原,计算属性保持数据单向,$nextTick。最终代码 drop-modal**


Vue中优雅“操作”dom之调整栏目顺序

动态组件

核心思路在于:动态组件 <component :is="componentName" />,通过操作数组navs的元素位置来控制栏目顺序。

navs中每个对象的key即componentName,hideMore来控制标题的右侧是否显示更多的链接。
navs: [
    {
      name: ''独家放送'',
      key: ''privateContent'',
      hideMore: true
    },
    {
      name: ''最新音乐'',
      key: ''newSong''
    },
    {
      name: ''推荐歌单'',
      key: ''playlist''
    },
    {
      name: ''推荐MV'',
      key: ''mv''
    },
    {
      name: ''主播电台'',
      key: ''dj''
    }
  ]
<div v-for="nav in navs">
    <component :is="nav.key" />
</div>

h5的拖拽api

接下来就是如何操作数组navs的问题了~ 通过h5的拖拽api改变元素位置并将新位置newNavs持久化保存,在页面初始化时使用newNavs渲染栏目组件即可。

此外还结合了 transition-group 组件,让栏目顺序变化有一个过渡效果,而这一过渡效果也很好的诠释了动画的重要意义--“解释刚刚发生了什么”

核心代码如下:

<div
    v-for="nav in navs"
    :key="nav.key"
    draggable="true"
    @dragstart="dragstart(nav)"
    @dragenter="dragenter(nav)"
>
    <span>{{nav.name}}</span>
    <z-icon type="drag"></z-icon>
</div>

data () {
    return {
        oldNav: 0,
          newNav: 0,
    }
}

methods: {
    dragstart (nav) {
      this.oldNav = nav
    },
    dragenter (nav) {
        this.newNav = nav
        if (this.oldNav.name !== this.newNav.name) {
          let oldIndex = this.navs.findIndex(nav => nav.name == this.oldNav.name)
          let newIndex = this.navs.findIndex(nav => nav.name == this.newNav.name)
          let newItems = [...this.navs]
          newItems.splice(oldIndex, 1)
          newItems.splice(newIndex, 0, this.oldNav)
          this.navs = [...newItems]
          window.localStorage.setItem(''nav'', JSON.stringify(this.navs))
      }
    }
}

最终实现的效果如下:

其他

项目中优雅操作dom的地方还很多,原理大同小异,即数据驱动。比如进度条组件 <divref="buffered" :></div> 通过操作变量bufferedOffsetWidth来控制缓冲条的width
又比如私人fm的歌曲卡片切换,篇幅有限不做过多介绍,详情请移步fm源码查看

音频可视化

AudioContext

音频可视化生动点长这样,还是挺炫酷的!!!

项目结合了两者实现了如下效果:射线和动态粒子,区别在于我的射线较细较短较密集(当然这些都是可控的),以及粒子是向圆内波动

音频的可视化要点在于使用canvas绘制基于AudioContext获取到频谱数据。

首先获取频谱数据

    // 获取API
    let context = new AudioContext;
    // 加载audio,可以是dom也可以是一个Audio的实例
    let audio = new Audio("1.mp3");
    // 创建节点
    let source = context.createMediaElementSource(audio);
    let analyser = context.createAnalyser();
    // 连接:source → analyser → destination
    source.connect(analyser);
    analyser.connect(context.destination);
    // 创建数据
    let output = new Uint8Array(460);
    // 获取频域数据
    analyser.getByteFrequencyData(output)

打印output,它长这样:

使用canvas绘制

首先绘制静态的外射线,注意观察每条射线

  const { width, height } = document.getElementById(''canvas'')
  const du = 3 // 圆心到两条射线距离所成的角度,即射线的间隙
  const potInt = { x: width / 2, y: height / 2 } // 起始坐标,即画布中心
  const R = 150 // 半径
  const W = 4 // 射线的宽度
  const L = 32 // 射线的长度
  • 圆角:cxt.lineCap = ''round''
  • 渐变:cxt.createLinearGradient(x1,y1,x2,y2)
  • 起始点:(Math.sin(((i * du) / 180) * Math.PI) * R + potInt.y,-Math.cos(((i * du) / 180) * Math.PI) * R + potInt.x)
  • 结束点:(Math.sin(((i * du) / 180) * Math.PI) * (R + L) + potInt.y, -Math.cos(((i * du) / 180) * Math.PI) * (R + L) + potInt.x)
其中i为循环360度的索引。确定了每条射线的起始点和结束点,也就确定了渐变的起始点和结束点。通过moveTo,lineTo绘制

紧接着将半径R扩大 let Rv = R + value ,先写死1再绘制一层纯色层叠加在渐变层之上。之后在requestAnimationFrame的执行函数中根据频谱数据动态改变value即可实现动画效果,但要注意渐变层的射线应该总是大于纯色层射线L的长度。

canvas动画当然是少不了 cxt.clearRect(0, 0, width, height)requestAnimationFrame 啦!动画及粒子向内的波动实现请参考musicView源码

除此之外还实现了另一种类似熔浆喷发的效果,也很nice。

渲染进程之间的即时通讯

项目一大重点难点是如何将store中歌词,播放状态等数据实时的在各窗体中共享。一开始想通过主进程来做中转,但主进程微笑而不失礼貌地婉拒了:“渲染进程能处理的事就不要拿来骚扰我啦,我很忙的!”。最后把目光投向了localstorage

// 监听storage改变时触发更新state
window.addEventListener(''storage'', () => {
    initState()
})

// 订阅mutation改变storage
store.subscribe((mutation, state) => {
    localStorage.setItem(STOREKEY, JSON.stringify(getState(state)))
})

其原理在于订阅mutation改变storage,监听storage触发更新state,通过书写一个vuex插件来实现这一功能,详情请查看 keep-state.js

usage:

在store入口文件引入keep-state,keep-state插件是一个函数,传入需要监听模块mudules执行函数,在初始化stroe时将函数的执行结果赋予plugins。

import persistStatePlugin from ''./plugins/keep-state''
const myPlugin = persistStatePlugin([''User'', ''play'', ''Localsong'', ''Setting'', ''Update''])
const store = new Vuex.Store({
  ...
  plugins: [myPlugin]
})

electron实战之桌面歌词

实现桌面歌词需要注意以下几点:

  1. 透明窗体
  2. 窗口在别的窗口上面
  3. 可锁定(锁定后忽略窗口内的所有鼠标事件)
  4. 出现在屏幕的位置如何确定

通过设置transparent:true,alwaysOnTop: true可分别实现窗体透明和窗体置顶,其中透明窗体要注意html,body,#app等不能设置非透明的背景色。

通过 setignoremouseeventsignore api可切换锁定窗体。

至于窗体初始时的位置,默认是屏幕中央。我想让他水平居中,垂直在任务栏偏上一点,这就需要获取屏幕的高来做点文章了 const { height } = electron.screen.getPrimaryDisplay().workAreaSize

最终窗体初始化的核心代码如下:

const options = {
    frame: false,
    x: 0,
    y: height - 150,
    fullscreenable: false,
    minimizable: false,
    maximizable: false,
    transparent: true,
    alwaysOnTop: true,
    skipTaskbar: true, // 任务栏中不显示窗口面板
    closable: false
}

const winURL = process.env.NODE_ENV === ''development''
  ? `http://localhost:9080/#desktop-lyric`
  : `file://${__dirname}/index.html#desktop-lyric`

let lyricWindow = new BrowserWindow(options)
lyricWindow.loadURL(winURL)

electron实战之mini模式

mini模式主要分为两部分:

  1. 主面板
  2. 当前播放列表面板

其中主面板又分三个面板:

  1. 歌曲缩略图,按住可拖动
  2. 歌曲信息及工具栏
  3. 相关操作面板

实现要点在于隐藏主窗体,显示mini窗体(320*50)。通过win.setBounds()在切换下拉列表时动态改变窗体大小

electron实战之自定义托盘菜单

通过electron Tray模块的实例的setContextMenu方法创建的菜单是真的丑不忍睹..

如何自定义一个托盘菜单呢?就像这样:

答案之一就是通过一个窗体来模拟。通过监听托盘的右键点击事件切换菜单的显示隐藏即可,其中需要实时计算出每次菜单出现的位置及边界情况。

electron实战之自定义任务栏的缩略图工具栏

任务栏工具栏?长这样,包含标题缩略图,及歌曲的相关操作。

幸运的,electron提供相关API实现这一功能 缩略图工具栏

electron实战之拖拽播放

介绍

拖拽播放分三种:

  1. 将文件拖到主窗体内实现播放
  2. 将文件拖动到桌面上的快捷方式图标打开客户端并播放
  3. 客户端已经打开,将文件拖动到桌面上的快捷方式图标实现播放(不会打开第二个实例)

禁用默认行为

在实现之前请先看看默认将文件拖动到客户端会发生什么?
是的,默认和将文件拖动到Chrome浏览器是一样的,就像这样...

就猜到会是这样了...!

所以我们第一步就是要禁用掉这些默认行为:

  window.ondragenter = (event) => {
      event.preventDefault()
  }
  window.ondragover = (event) => {
      event.preventDefault()
  }

将文件拖到主窗体内实现播放

通过监听window的drop事件来实现我们的打开文件操作。这只是实现了拖拽播放中的第一种情况。

window.ondrop = openFilesOndrop

其他两种情况在windows平台上需要在process.argv上动动手脚。

将文件拖动到桌面上的快捷方式图标打开客户端并播放

先说说第二种情况,在主进程的appready的事件回调中将process.argv赋予全局变量global global.argv = process.argv,在渲染进程中通过electron的remote模块的getGlobal方法获取到argv。process.argv初始化长这样:["E:\electron-vue-cloud-music\网易云音乐.exe"] 即客户端的可执行文件的路径。所以在执行handleWillOpenFiles方法前判断一下数组长度。在handleWillOpenFiles方法过滤出.mp3文件进行相关解析播放等操作。详情移步 createdInit

import { remote } from ''electron''
const startArgv = remote.getGlobal(''argv'')
  if (startArgv.length > 1) {
      handleWillOpenFiles(startArgv)
  }

客户端已经打开,将文件拖动到桌面上的快捷方式图标实现播放

至于第三种情况和第二种大同小异,区别在于argv的参数的获取以及渲染进程如何拿到argv。对于argv的获取,在主进程的app的second-instance监听回调中获取,通过自定义事件分发,渲染进程监听该自定义事件来接受。

// 主进程
app.on(''second-instance'', (event, argv, workingDirectory) => {
    if (mainWindow) {
        mainWindow.webContents.send(''open-files'', {argv})
    }
})
// 渲染进程
import { ipcRenderer} from ''electron''
ipcRenderer.on(''open-files'', async (event, args) => {
    let { argv } = args
    handleWillOpenFiles(argv)
})

electron实战之自动/手动检查更新

当前自动更新已移除,简单说说如何实现手动检查更新,具体流程是这样的:

  1. 开发,commit
  2. npm version patch && git push origin master && git push origin --tags
  3. Travis CL,AppVeyor监测到master变化自动构建
  4. github上编辑发布远程版本
  5. 用户/客户端触发检查更新
  6. 客户端调用github API获取最新的远程版本号与本地版本号对比
  7. 如若需要更新显示更新窗体引导下载安装


下载完成后关闭窗体并打开下载文件进行安装

electron实战之Nedb数据库持久化

Nedb数据库 主要用来存储下载的歌曲列表及歌词。盗用官网介绍就是:

Embedded persistent or in memory database for Node.js, nw.js, Electron and browsers, 100% JavaScript, no binary dependency. API is a subset of MongoDB''s and it''s plenty fast.
本人4级水平简短白话翻译是为Electron而生,无依赖,快,使用和mongoDb差不多

electron实战之打包自定义安装路径,安装界面美化

自定义安装路径较为简单在package.json中找到build字段加入以下代码即可

"nsis": {
  "oneClick": false, // 是否一键安装
  "allowToChangeInstallationDirectory": true // 是否允许修改安装路径
}

自定义安装界面可通过一些开源工具来快捷实现如 NSIS-UI 简单实现了一下,效果还可以:

electron实战之自定义协议实现浏览器中启动客户端

通过app.setAsDefaultProtocolClient可实现自定义协议在浏览器中唤起客户端,如果安装过了可尝试 打开electron云音乐

electron实战之离线/在线侦测与桌面通知

通过window的onlineoffline可监听网络状态。

通过navigator.onLine可判断当前网络状态.

通过h5的Notification可实现桌面通知,在window平台中使用请确保设置appId

Travis CL,AppVeyor自动构建

分享一篇阮一峰的一篇文章即可 持续集成


结语

当前项目只对window平台进行测试。

至此electron云音乐实战分享基本结束,项目中有趣的地方还有很多,但篇幅有限,不能面面俱到。本来还想说说那些令人敬礼的css但再不去打lol的衰减局就要掉峡谷宗师了!不排除有下集..第一次写文章,感谢各位看客老爷看到这里,谢谢。

最后唠叨一句:“觉得不错给我一个赞~”

其他界面预览(多图预警)

localplayer.png










animatePicture.gif
mini2.pngview1.gif
tray.pngview2.gif

Ant Design Mobile Ant Design Mobile Ant Design 移动端设计规范的 React 实现

Ant Design Mobile Ant Design Mobile Ant Design 移动端设计规范的 React 实现

Ant Design Mobile Ant Design Mobile 介绍

Ant Design Mobile

Ant Design 移动端设计规范,一个基于
Preact/React/React Native 的 UI 组件库。antd-mobile 是 Ant Design 的移动规范的 React
实现,服务于蚂蚁及口碑无线业务。

  • 基于 Ant Design 移动设计规范。

  • 规则化的视觉样式配置,适应各类产品风格。

  • 基于 React Native 的多平台支持。

  • 使用 TypeScript 开发,提供类型定义文件。

  • iOS

  • Android 4.0+

适用场景

  • 适合于中大型产品应用

  • 适合于基于 react / preact / react-native 的多终端应用

  • 适合不同 UI 风格的高度定制需求的应用

Ant Design Mobile Ant Design Mobile 官网

https://mobile.ant.design/index-cn

Ant Design of Vue select框获取key和name的问题

Ant Design of Vue select框获取key和name的问题

Ant Design of Vue select框获取key和name

加入label-in-value这个属性

<a-form-item label="分类">
  <a-select
    placeholder="请选择分类"
       label-in-value
    v-decorator="[''knowledgeunit'', { rules: [{ required: true, message: ''请选择分类'' }] }]"
  >
    <a-select-option v-for="(calssitem, index) in classflyData" :key="index" :value="calssitem.Code">
      {{ calssitem.Name }}
    </a-select-option>
  </a-select>
</a-form-item>

获取到的value 就会变成 {key: 1, lable: ''名字''} 的形式

获取值的时候可以这样获取

this.addResourceForm.validateFields((err, values) => {
   if (err && this.newChange.length > 0) {
     return
   }
   const saveObj = {}
   saveObj.knowledgeunit = values.knowledgeunit.key // 获取的值
   saveObj.source = values.knowledgeunit.label  // 获取的名称
 })

我的记录

还有一种方法

你如果想获取怎个对象,怎么获取呢?

<a-form-item label="分类">
  <a-select
    placeholder="请选择分类"
       @change="onChange"
    v-decorator="[''knowledgeunit'', { rules: [{ required: true, message: ''请选择分类'' }] }]"
  >
    <a-select-option v-for="(calssitem, index) in classflyData" :key="index" :value="calssitem.Code">
      {{ calssitem.Name }}
    </a-select-option>
  </a-select>
</a-form-item>

加一个onChange方法,根据下标获取对应的对象

 onChange (item) {
   const obj = this.list[item]
   console.log(obj)
 }

Ant Design Vue使用select出现的问题

1.select下拉菜单滚动条滚动后,自动弹回到顶部

解决方法:

a-select-option 使用v-for渲染时,key值不能重复或者为null

2.下拉列表在局部滚动时不跟随,与select框分离

解决方法:

<a-select
:getPopupContainer="(triggerNode)=>{ return triggerNode.parentNode || document.body;}" 
>

以上为个人经验,希望能给大家一个参考,也希望大家多多支持。

您可能感兴趣的文章:
  • Vue中keyup.enter和blur事件冲突的问题及解决
  • vue中@keyup.enter失效问题及解决
  • vue对象添加属性(key:value)、显示和删除属性方式
  • Vue深入理解之v-for中key的真正作用
  • Vue开发实例探究key的作用详解

ant design of vue 中的select问题

ant design of vue 中的select问题

在做项目中使用ant design of vue 的ui框架,

使用select做省市区联动的时候,发现v-model和placehoder不能共用。

解决办法:

<a-select v-model="provinceId" placeholder="请选择省份"@change="provinceChanged" allowClear>
          <a-select-option v-for="item in provinces" :key="item.id">{{item.name}}</a-select-option>
        </a-select>
        <a-select v-model="cityId" placeholder="请选择城市"@change="cityChanged" allowClear>
          <a-select-option v-for="item in cities" :key="item.id">{{item.name}}</a-select-option>
        </a-select>

js:

一定要记住provinceId,和cityId 默认要设置为undefiend,否则不会显示placeholder内容

我们今天的关于Ant Design Vue中TreeSelect详解ant design vue tree的分享就到这里,谢谢您的阅读,如果想了解更多关于2019Electron+Vue+Ant Design Vue仿网易云音乐windows客户端实战分享、Ant Design Mobile Ant Design Mobile Ant Design 移动端设计规范的 React 实现、Ant Design of Vue select框获取key和name的问题、ant design of vue 中的select问题的相关信息,可以在本站进行搜索。

本文标签: