Skip to content

案例

瀑布流

父组件

vue

<template>
	// 父向子传参 props
	<Child :list="list"></Child>
</template>

<script setup lang='ts'>
import {ref, reactive} from 'vue'
import Child from "./components/child.vue";

const list = [
	{
		height: 300,
		background: 'red'
	},
	{
		height: 400,
		background: 'pink'
	},
	{
		height: 500,
		background: 'blue'
	},
	{
		height: 200,
		background: 'green'
	},
	{
		height: 300,
		background: 'gray'
	},
	{
		height: 400,
		background: '#CC00FF'
	},
	{
		height: 200,
		background: 'black'
	},
	{
		height: 100,
		background: '#996666'
	},
	{
		height: 500,
		background: 'skyblue'
	},
	{
		height: 300,
		background: '#993366'
	},
	{
		height: 100,
		background: '#33FF33'
	},
	{
		height: 400,
		background: 'skyblue'
	},
	{
		height: 200,
		background: '#6633CC'
	},
	{
		height: 300,
		background: '#666699'
	},
	{
		height: 300,
		background: '#66CCFF'
	},
	{
		height: 300,
		background: 'skyblue'
	},
	{
		height: 200,
		background: '#CC3366'
	},
	{
		height: 200,
		background: '#CC9966'
	},
	{
		height: 200,
		background: '#FF00FF'
	},
	{
		height: 500,
		background: '#990000'
	},
	{
		height: 400,
		background: 'red'
	},
	{
		height: 100,
		background: '#999966'
	},
	{
		height: 200,
		background: '#CCCC66'
	},
	{
		height: 300,
		background: '#FF33FF'
	},
	{
		height: 400,
		background: '#FFFF66'
	},
	{
		height: 200,
		background: 'red'
	},
	{
		height: 100,
		background: 'skyblue'
	},
	{
		height: 200,
		background: '#33CC00'
	},
	{
		height: 300,
		background: '#330033'
	},
	{
		height: 100,
		background: '#0066CC'
	},
	{
		height: 200,
		background: 'skyblue'
	},
	{
		height: 100,
		background: '#006666'
	},
	{
		height: 200,
		background: 'yellow'
	},
	{
		height: 300,
		background: 'yellow'
	},
	{
		height: 100,
		background: '#33CCFF'
	},
	{
		height: 400,
		background: 'yellow'
	},
	{
		height: 400,
		background: 'yellow'
	},
	{
		height: 200,
		background: '#33FF00'
	},
	{
		height: 300,
		background: 'yellow'
	},
	{
		height: 100,
		background: 'green'
	}

]
</script>

<style lang='scss'>
#app,
html,
body {
	height: 100%;
}

* {
	padding: 0;
	margin: 0;
}
</style>

子组件

vue

<template>
	<div class="wraps">
		<div :style="{height:item.height+'px',background:item.background,left:item.left+'px',top:item.top+'px'}"
		     v-for="(item,index) in waterList" :key="index" class="items"></div>
	</div>
</template>

<script setup lang="ts">
import {onMounted, reactive} from "vue";

// 接收父组件的传参
const props = defineProps<{
	list: Array<any>
}>()

//定义第一行的数组
const waterList = reactive<Array<any>>([])
//定义一个用来统计第一行高度的数组
const heightList = reactive<number[]>([])
const init = () => {
	const width = 130
	const x = document.body.clientWidth
	console.log(x)
	const column = Math.floor(x / width)
	// console.log(column)
	// console.log(props.list)
	
	//遍历
	for (let i = 0; i < props.list.length; i++) {
		//第一行的div
		if (i < column) {
			props.list[i].left = i * width
			props.list[i].top = 20
			waterList.push(props.list[i])
			heightList.push(props.list[i].height)
		} else {
			// 定义最小高度
			let current = heightList[0]
			// 最小项索引
			let index = 0
			heightList.forEach((height, ind) => {
				if (current > height) {
					current = height
					index = ind
				}
			})
			props.list[i].top = current + 40
			props.list[i].left = index * width
			heightList[index] = heightList[index] + 20 + props.list[i].height
			waterList.push(props.list[i])
		}
	}
}
onMounted(() => {
	init()
})
</script>


<style scoped lang="scss">
.wraps {
	position: relative;
	height: 100%;
	
	.items {
		position: absolute;
		width: 120px;
	
	}
}

</style>

富文本编辑器

使用tinymce

shell
ni @tinymce/tinymce-vue tinymce

App.vue

init

vue
<script setup lang="ts">
import { onMounted } from 'vue'
import tinymce from 'tinymce'

onMounted(() => {
  tinymce.init({
    selector: '#mytiny',
  })
})
</script>

<template>
  <div id="mytiny" />
</template>

<style scoped>
</style>

TIP

node_modules 中的 tinymce 文件夹中的 icons models plugins skins themes 五个文件夹复制到 public 文件夹中

修改样式

vue
<script setup lang="ts">
import { onMounted } from 'vue'
import tinymce from 'tinymce'

onMounted(() => {
  tinymce.init({
    selector: '#mytiny',
    statusbar: false, // //底部状态栏
    menubar: false, // //顶部菜单栏
    toobar: false, // //工具栏
  })
})
</script>

使用 Editor 组件

vue
<script setup lang="ts">
import Editor from '@tinymce/tinymce-vue'

const initObj = {
  statusbar: true,
  menubar: true,
  toolbar: true,
}
</script>

<template>
  <Editor :init="initObj" />
</template>

<style scoped>
</style>

中文化

找到 Chinese Simplified

将 langs 文件夹放在 public 下

vue
<script setup lang="ts">
import { onMounted } from 'vue'
import tinymce from 'tinymce'

const initObj = {
  selector: '#mytiny',
  statusbar: true,
  menubar: true,
  toolbar: true,
  skin: 'oxide-dark', // //换肤
  language: 'zh-Hans',// //语言
}
onMounted(() => {
  tinymce.init(initObj)
})
</script>

修改工具栏内容

Toolbar Buttons Available for TinyMCE

vue
<script setup lang="ts">
import { onMounted } from 'vue'
import tinymce from 'tinymce'

onMounted(() => {
  tinymce.init({
    selector: '#mytiny',
    statusbar: true,
    menubar: true,
    skin: 'oxide-dark',
    language: 'zh-Hans',
    toolbar: 'undo redo | styles | bold italic | alignleft aligncenter',// //工具栏
    width: 600,
  })
})
</script>

修改顶部菜单栏

Basic menu options

vue
<script setup lang="ts">
import { onMounted } from 'vue'
import tinymce from 'tinymce'

onMounted(() => {
  tinymce.init({
    selector: '#mytiny',
    statusbar: true,
    menu: {
      file: { title: 'File', items: 'newdocument restoredraft | preview | export print | deleteallconversations' },
      edit: { title: 'Edit', items: 'undo redo | cut copy paste pastetext | selectall | searchreplace' },
    },
    menubar: 'file',
    skin: 'oxide-dark',
    language: 'zh-Hans',
    width: 600,
  })
})
</script>

TIP

menu 需要搭配 menubar 一起使用,不然不能隐藏其中的某些不想要的项

获取文本内容

tinymce.activeEditor.getContent() 方法获得

不填写参数 或者使用 { format: 'html' } 作为参数得到的是html

使用 { format: 'text' } 得到文本

js
function send() {
  console.log(tinymce.activeEditor.getContent())
  console.log(tinymce.activeEditor.getContent({ format: 'text' }))
}

设置文本内容

tinymce.activeEditor.setContent() 方法设置

参数里写要设置的文本,直接写文本就是使用p标签的文本,也可以使用html写法

js
function setInContent() {
  // tinymce.activeEditor.setContent('123')
  tinymce.activeEditor.setContent('<h1>hello world</h1>')
}

获取选中的内容进行操作

tinymce.activeEditor.selection 方法进行获取

获取选中的文本 tinymce.activeEditor.selection.getContent()

修改选中的文本 tinymce.activeEditor.selection.setContent('hello')

使用插件

增加 plugins 属性,在 toolbar 中添加新增的插件名称

vue
<script>
onMounted(() => {
  tinymce.init({
    selector: '#mytiny',
    statusbar: true,
    menu: {
      file: { title: 'File', items: 'newdocument restoredraft | preview | export print | deleteallconversations' },
      edit: { title: 'Edit', items: 'undo redo | cut copy paste pastetext | selectall | searchreplace' },
    },
    menubar: 'file edit',
    skin: 'oxide-dark',
    plugins: 'image code table', 
    language: 'zh-Hans',
    toolbar: 'undo redo | styles | bold italic | alignleft aligncenter | image code table', 
    width: 600,
  })
})
</script>

自定义按钮

使用 tinymce.editor.ui.Registry

vue
<script >
onMounted(() => {
  tinymce.init({
    selector: '#mytiny',
    statusbar: true,
    menubar: 'file edit',
    skin: 'oxide-dark',
    plugins: 'image code table',
    setup(editor) { 
      console.log('editor', editor) 
      editor.ui.registry.addButton('red', { 
        icon: 'help', 
        tooltip: '变红', 
        onAction: () => { 
          console.log(1) 
        }, 
      }) 
    }, 
    language: 'zh-Hans',
    toolbar: 'undo redo | styles | bold italic | red | image code table', 
    width: 600,
  })
})
</script>

将选中内容改变样式

vue
<script>
onMounted(() => {
  tinymce.init({
    selector: '#mytiny',
    statusbar: true,
    menu: {
      file: { title: 'File', items: 'newdocument restoredraft | preview | export print | deleteallconversations' },
      edit: { title: 'Edit', items: 'undo redo | cut copy paste pastetext | selectall | searchreplace' },
    },
    menubar: 'file edit',
    skin: 'oxide-dark',
    plugins: 'image code table',
    setup(editor) {
      console.log('editor', editor)
      editor.ui.registry.addButton('red', {
        icon: 'help',
        tooltip: '变红',
        onAction: () => {
          // 获取选中文字 //
          const text = editor.selection.getContent({ format: 'text' }) 
          editor.selection.setContent(`<span class="red-class">${text}</span>`) 
        },
      })
    },
    language: 'zh-Hans',
    toolbar: 'undo redo | styles | bold italic | red showVuePop | image code table',
    width: 600,
    content_css: '/mycontent.css',
  })
})
</script>

content_css: '/mycontent.css' 中的 mycontent.css 文件 放在 public 下面