vue步骤条组件 vue组件布局
Vue——自定义组件 & 自定义$emit & 插槽slot
'date': '2017-12-16'局部注册的组件,只能在当前Vue实例中使用,并且在其子组件中不可用。
vue步骤条组件 vue组件布局
vue步骤条组件 vue组件布局
在 components 选项中定义局部组件。每个组件就是一个小型的Vue实例,它里面除了不能设置el选项,其他选项它都有。
组件名称: 自定义,可以使用驼峰命名方式或者短横线的命名方式,但是需要注意的是如果应用到DOM中,就只能用短横线命名的方式,否则就会报错。注意组件的名称不要跟原生html元素重名。
template选项: 定义组件的模板。模板中必须包含一个根标签。
props选项: 定义组件标签上的属性。驼峰命名法的 prop 名(tTitle)需要使用其等价的短横线分隔命名法(t-title)命名。注意:props是只读的,不能修改( 解决办法: 在data中对props接收到的数据进行中转)。
data: 定义组件的数据。注意:Vue实例的data选项可以是一个对象,也可以是一个方法,由该方法返回一个对象。 但是在组件中,data选项必须是一个方法,由该方法返回一个对象。因为组件可能会使用很多次,如果data选项是对象的话,会导致多个组件使用了同一份数据。
全局注册的组件可以用在任何新创建的 Vue 根实例 (new Vue) 的模板中。
$emit()用于触发自定义。注意:名称中不能采用大写字母。
效'title': '无缝滚动第二行无缝滚动第二行',果:
效果:
slot 用于在组件的内部定义插槽,组件标签之间的所有html内容,会在插槽所在位置呈现。
效果:
在vue-cli中如何实现组件通信
本篇文章主要介绍了在vue-cli中组件通信的方法,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
本文介绍了在vue-cli中组件通信的方法,分享给大家。具体如下:
vue组件之间的通信包括三种:
1.父组件向子组件通信
2.子组件向父组件通信
3.同级组件之间的通信
一.父传子组件通信
拿app.vue当父组件,content.vue当子组件
import contents from './components/content';2.在父组件中注册子组件
data() {
return {
test:'0'
},
components:{
'v-header':headers,
'v-content':contents
}3.子组件通过props来接收数据
子组件:
down() {
this.$emit('down','null'); //主动触发down方法,'null'为向父组件传递的数据
}}父组件:
changes(msg) {
this.test= test;
}}二.非父子组件通信
//把a当作一个中转站
var a = new Vue();组件1触发:
mods:{
(){
a.$emit("change",'null')
}}组件2接收:
created(){
a.$on('change',()=>{
this.msg =cancel () { 'null'
})
}上面是我整理给大家的,希望今后会对大家有帮助。
相关文章:
在vue-cli中如何实现移动端自适应
在Vue 组件Toast中如何实现显示框效果
有关webpack中rules参数处理
在AngularJS中如何实现简单的计算
如何理解vue中的全局组件和局部组件
vue中的全局组件指的是可以在应用程序中的任何位置使用的组件,而局部组件指的是未在全局组件中注册的组件,因此只能使用于局部。
在Vue中组件的出现是为了拆分Vue实例的代码量,让我们以不同的组件来划分不同的功能模块。在代码中我们需要何种功能就去调用相应的组件就可以了。接下来要介绍的是全局组件和局部组件的区别,具有一定的参考作用,希望对大家有所帮助。
【教程:Vue教程】
全局组件指的是可以在应用程序中的任何位置使用的组件,包括在其他组件中
局部组件指的是未在全局组件中注册的组件,因此只能在注册它的组件上使用
例使用 Vueponent 来创建全局组件。Vueponent的个参数就是组件名。:
return {
email: '@mycompany'
},
template: `
Contact Us
Please send an e-mail to: {{ email }}
`});new Vue({ el: '#app',});上述代码的组件实际上是一个全局组件,因为我们在全局Vue对象上使用组件方法去注册它。这样就意味着我们可以随意的使用它。
如何将全局组件设置成局部组件
先将组件对象存储在变量中
var contactUs = { data: function() {
return {
email: '@mycompany'
},
template: `
Contact Us
Please send an e-mail to: {{ email }}
`};然后在Vue实例中,我们可以添加一个components属性,其中包含我们想要局部注册的组件。此属性应该是一个对象,并包含标记名称和配置对象的键值对。
new Vue({
el: '#app',
components: {
'contact-us': contactUs
}});请注意,在此示例中,已将components属性添加到Vue实例,但也可以将其添加到另一个组件。
运行代码后会看到该组件已经正常工作了。但是为了证明该组件是局部的而不是全局的将添加另一个Vue实例并更改现有实例的选择器。
new Vue({
el: '#app1',
components: {
'contact-us': contactUs
}});new Vue({ el: '#app2',});
现在我们只看到一次呈现的组件,即使我们在模板中使用了两次标签。
它出现在个Vue实例中,因为我们已将其注册为局部组件,但第二个Vue实例不知道如何处理标记。查看一下浏览器的控制台,浏览器报错说未注册该组件
因此,要注册全局组件,请使用Vueponent方法,对于局部组件,应使用Vue实例或其他组件中的components属性。
总结:
Vue3_15(全局组件,局部组件,递归组件)
1.父组件中导入子组件(子组件导出)例如组件使用频率非常高(table,Input,button,等)这些组件 几乎每个页面都在使用便可以封装成全局组件
案例------我这儿封装一个Card组件想在任何地方去使用
使用方法
在main.ts 引入我们的组件跟随在createApp(App) 后面 切记不能放到mount 后面这是一个链式调用用
其次调用 component 个参数组件名称 第二个参数组件实例
使用方法
直接在其他vue页面 立即使用即可 无需引入
就是在一个组件内(A) 通过import 去引入别的组件(B) 称之为局部组件
应为B组件只能在A组件内使用 所以是局部组件
如果C组件想用B组件 就需要C组件也手动import 引入 B 组件
原理跟我们写js递归是一样的 this.isHide = !this.isHide;自己调用自己 通过一个条件来结束递归 否则导致内存泄漏
案例递归树
在父组件配置数据结构 数组对象格式 传给子组件
子组件接收值
template
TreeItem 其实就是当前组件 通过import 把自身又引入了一遍 如果他没有children 了就结束
15《Vue 入门教程》Vue 动态组件 & keep-alive
这次给大家带来怎样进行Vue拖拽组件开发,进行Vue拖拽组件开发的注意事项有哪些,下面就是实战案例,一起来看一下。本小节我们将介绍 Vue 的动态组件,以及缓存 keep-alive 的使用。包括动态组件的使用方法,以及如何使用 keep-alive 实现组件的缓存效果。
动态组件是让多个组件使用同一个挂载点,并动态切换。动态组件是 Vue 的一个高级用法,但其实它的使用非常简单。keep-alive 是 vue 的内置组件,能在组件切换过程中将状态保存在内存中,防止重复渲染 DOM。
通过使用保留的 元素,动态地把组件名称绑定到它的 is 特性,可以实现动态组件:
实例演示
"运行案例" 可查看在线运行效果
代码解释: HTML 代码第 2 行,我们使用动态组件 component,将当前需要展示的组件名通过变量 currentView 绑定到 component 的 is 属性上。 HTML 代码第 3-5 行,我们定义了三个按钮,通过点击按钮切换 currentView 的值。 JS 代码第 3-11 行,我们定义了组件 ComponentA、ComponentB、ComponentC。
最终的实现效果是:当点击按钮的时候会动态切换展示的组件。
keep-alive 是 Vue 提供的一个抽象组件,用来对组件进行缓存,从而节省性能,由于是一个抽象组件,所以在页面渲染完毕后不会被渲染成一个 DOM 元素。被 keep-alive 缓存的组件只有在初次渲染时才会被创建,并且当组件切换时不会被销毁。
keep-alive 的用法相对简单,直接使用 keep-alive 包裹需要缓存的组件即可:
实例演示
"运行案例" 可查看在线运行效果
代码解释: HTML 代码第 2-3 行,我们使用 keep-alive 包裹动态组件 component,将当前需要展示的组件名通过变量 currentView 绑定到 component 的 is 属性上。 HTML 代码第 5-7 行,我们定义了三个按钮,通过点击按钮切换 currentView 的值。 JS 代码第 3-29 行,我们定义了组件 ComponentA、ComponentB、ComponentC,分别定义了他们的 created 和 beforeDestroy 。
之前我们介绍过, keep-alive 缓存的组件只有在初次渲染时才会被创建。所以,我们通过修改 currentView 切换组件时,组件的 beforeDestroy 不会触发。若该组件是次渲染,会触发 created ,当再次切换显示该组件时,created 不会再次触发。
activated 和 deactivated 和我们之前学习的生命周期函数一样,也是组件的生命周期函数。不过, activated 和 deactivated 只在 内的所有嵌套组件中触发。 activated :进入组件时触发。 deactivated :退出组件时触发。
示例代码:
实例演示
"运行案例" 可查看在线运行效果
代码解释: JS 代码中,我们定义了组件 ComponentA、ComponentB,并分别定义了他们的 activated 和 deactivated 函数。 HTML 代码第 2-3 行,我们使用 keep-alive 包裹动态组件 component,将当前需要展示的组件名通过变量 currentView 绑定到 component 的 is 属性上。 HTML 代码第 5-6 行,我们定义了两个按钮,通过点击按钮切换 currentView 的值。当我们切换组件显示时,可以看到这样的打印信息:
include 和 exclude 是 keep-alive 的两个属性,允许组件有条件地缓存。 include: 可以是字符串或正则表达式,用来表示只有名称匹配的组件会被缓存。 exclude: 可以是字符串或正则表达式,用来表示名称匹配的组件不会被缓存。
示例:
实例演示
"运行案例" 可查看在线运行效果
代码解释: HTML 代码第 2-4 行,我们使用 keep-alive 包裹动态组件 component。给 keep-alive 指定需要缓存组件 ComponentA,ComponentB。 在之前的小节我们了解到 keep-alive 缓存的组件只有在初次渲染时才会被创建。所以,在案例中,组件 ComponentA 和 ComponentB 的 created 函数只有在次组件被创建的时候才会触发,而 ComponentC 的 created 函数当每次组件显示的时候都会触发。
exclude 示例:
实例演示
"运行案例" 可查看在线运行效果
代码解释: HTML 代码第 2-4 行,我们使用 keep-alive 包裹动态组件 compon顺着这个思路走下去,我们知道:ent。给 keep-alive 指定不需要缓存组件 ComponentA,ComponentB。
本节,我们带大家学习了动态组件和缓存组件在项目中的运用。主要知识点有以下几点:
使用vue如何实现无缝滚动组件
本篇文章主要给大家讲解了vue的无缝滚动组件vue-seamless-scroll的用法,需要的朋友参考学习下吧。
}]Installation
NPM
npm install vue-seamless-scroll --seUsage
ES6
以下es6用法需要webpack环境编译.
class="white no-underline underline-hover">vue-seamless-scroll
无缝滚动demo
demo1 向上无缝滚动,hover可停止
var option = {
step: 0.5,
limitMoveNum: 5
}
class="warp">
v-text=".date">
demo2 limitMoveNum过大不滚动 开启了openWatch
3s后data增加到9条
var option = {
limitMoveNum: 7
}
@copy-data="listData1 = listData1.concat(listData1)" class="warp">
class="date" v-text=".date">
demo3 limitMoveNum过大不滚动 关闭了openWatch
3s后data增加到9条
var option = {
limitMoveNum: 7
openWatch: false
}
@copy-data="listData2 = listData2.concat(listData2)" class="warp">
class="date" v-text=".date">
demo4 向下滚动,禁止了hover悬停
var option = {
limitMoveNum: 5,
direction: 0,
hoverStop: false,
}
@copy-data="listData3 = listData3.concat(listData3)" class="warp">
class="date" v-text=".date">
demo5 向上无缝滚动,单条停止一段时间
var option = {
step: 0.5,
limitMoveNum: 5
singleHeight: 30,
waitTime: 1000
}
@copy-data="listData4 = listData4.concat(listData4)" class="warp">
v-text=".date">
import myClass from '../src/components/myClass.vue'
export default {
name: 'app',
data () {
return {
listData: [{
'title': '无缝滚动行无缝滚动行',
}, {
}, {
'title': '无缝滚动第三行无缝滚动第三行',
}, {
'title': '无缝滚动第四行无缝滚动第四行',
}, {
'title': '无缝滚动第五行无缝滚动第五行',
}, {
'title': '无缝滚动第六行无缝滚动第六行',
}, {
'title': '无缝滚动第七行无缝滚动第七行',
}, {
}, {
'title': '无缝滚动第九行无缝滚动第九行',
}],
listData1: [{
'title': '无缝滚动行无缝滚动行',
}, {
}, {
'title': '无缝滚动第三行无缝滚动第三行',
}, {
'title': '无缝滚动第四行无缝滚动第四行',
}, {
'title': '无缝滚动第五行无缝滚动第五行',
}, {
'title': '无缝滚动第六行无缝滚动第六行',
}],
listData2: [{
'title': '无缝滚动行无缝滚动行',
}, {
}, {
'title': '无缝滚动第三行无缝滚动第三行',
}, {
'title': '无缝滚动第四行无缝滚动第四行',
}, {
'title': '无缝滚动第五行无缝滚动第五行',
}, {
'title': '无缝滚动第六行无缝滚动第六行',
}],
listData3: [{
'title': '无缝滚动行无缝滚动行',
}, {
}, {
'title': '无缝滚动第三行无缝滚动第三行',
}, {
'title': '无缝滚动第四行无缝滚动第四行',
}, {
'title': '无缝滚动第五行无缝滚动第五行',
}, {
'title': '无缝滚动第六行无缝滚动第六行',
}, {
'title': '无缝滚动第七行无缝滚动第七行',
}, {
}],
listData4: [{
'title': '无缝滚动行无缝滚动行',
}, {
}, {
'title': '无缝滚动第三行无缝滚动第三行',
}, {
'title': '无缝滚动第四行无缝滚动第四行',
}, {
'title': '无缝滚动第五行无缝滚动第五行',
}, {
'title': '无缝滚动第六行无缝滚动第六行',
}, {
'title': '无
怎样进行vue弹窗组件使用
mods: {这次给大家带来怎样进行vue弹窗组件使用,vue弹窗组件使用的注意事项有哪些,下面就是实战案例,一起来看一下。
if(newIndex < this.dragList.length){弹窗是一个项目必备的复用利器,所以封装起来,保证项目ui一致,是很有必要的。学了一段时间vue,想想还是用vue写一下吧。用的很小白,但是会写出来了,说明我也有进步一丢丢了。继续加油?.
代码贴图如下,样式比较丑,不要介意?
p,h4{
margin:0;
}.modal{
width: 480px;
background-color: #fff;
border: 1px solid rgba(0, 0, 0, .3);
border-radius: 6px;
box-shadow: 0 4px 12px rgba(0, 0, 0, .5);
margin: 50px;
}.modal-header {
color: #fff;
background: cadetblue;
border-radius: 6px 6px 0 0;
padding: 15px;
border-bottom: 1px solid #5e9fa1;
}.modal-content p {
padding: 15px 10px;
}.modal-footer {
padding: 15px;
text-align: right;
border-top: 1px solid #e5e5e5;
}.btn {
border: 1px solid #d1d1d1;
border-radius: x;
background-color: #f7f7f7;
background: -webkit-gradient(linear, 0 0, 0 , from(#f7f7f7),
to(#f2f2f2));
background: -moz-gradient(linear, 0 0, 0 , from(#f7f7f7),
to(#f2f2f2));
background: -o-gradient(linear, 0 0, 0 , from(#f7f7f7), to(#f2f2f2));
background: -ms-gradient(linear, 0 0, 0 , from(#f7f7f7), to(#f2f2f2));
height: 28px;
padding: 0 20px;
cursor: pointer;
line-height: 28px;
display: inline-block;
color: #666666;
margin-right: 5px;
outline: none;
}.blue {
border: 1px solid #5e9fa1;
background-color: #5e9fa1;
background: -webkit-gradient(linear, 0 0, 0 , from(#74c4c6),
to(#5e9fa1));
background: -moz-gradient(linear, 0 0, 0 , from(#74c4c6),
to(#5e9fa1));
background: -o-gradient(linear, 0 0, 0 , from(#74c4c6), to(#5e9fa1));
background: -ms-gradient(linear, 0 0, 0 , from(#74c4c6), to(#5e9fa1));
color: #FFFFFF;
}
v-if="!isHide" modal-title="温馨提示" ok-btn="确认购买" cancel-btn="去意已决" @on-ok="ok" @on-cancel="cancel" > 尊敬的用户,您购买的商品将于支付成功后3-7个工作日内发货,敬请周知。祝您购物愉快!
/
props:
modalTitle: 弹窗标题
okBtn: 确认按钮
cancelBtn: 取消按钮
注意事项:传参时候使用烤串的书写方式xx-xxx
slot:
modal-content: 内容区域
modal-footer: 页脚按钮区域
mods:
okHandle: 触发确认on-ok自定义
cancelHandle: 触发取消on-cancel自定义
/
Vueponent('ys-modal-component', {
props: {
modalTitle: {
type: String,
default: '标题区域'
},
okBtn: {
type: String,
default: '确认'
},
cancelBtn: {
type: String,
default: '取消'
}},
template: `
{{ modalTitle }}
`,
okHandle () {
console.log("点击确定");
this.$emit("on-ok");
},
cancelHandle () {
console.log("点击取消");
this.$emit("on-cancel");
})
new Vue({
el: "#app",
data: {
isHide: false
},
ok () {
alert("欢迎您购买本产品");
},
})
相信看了本文案例你已经掌握了方法,更多精彩请关注Gxl网其它相关文章!
阅读:
如何使用Vue实现PopupWindow组件
怎样使用vue+jquery+lodash实现滑动时顶部悬浮
在Vue.js中如何实现组件间循环引用
方法二组件(Component)是 Vue.js 最强大的功能之一。 组件可以扩展 HTML 元素,封装可重用的代码。下面这篇文章主要给大家介绍了关于Vue.js组件间循环引用的相关资料,文中通过示例代码介绍的非常详细,需要的朋友可以参考下。
_ ,若手指离开元素,那么我们在touchend中,通过this.dragList.spl(oldIndex, 1),this.dragList.spl(newIndex, 0, )重新调整数组顺序。页面会根据的dragList渲染列表。什么是组件:
众所周知组件是Vue.js最强大的功能之一。组件可以扩展HTML元素,封装可重用的代码。在较高层面上,组件是自定义的元素,Vue.js的编译器为它添加特殊功能。在有些情况下,组件也可以是原生HTML元素的形式,以is特性扩展。下面话不多说了,来一起看看本文的正文内容。
引言
写了大大小小不少基于vue的项目,但是基本没用到过组件循环引用的知识。
为了查缺补漏,照着文档撸一个DEMO:组件之间的循环引用
本人的运行版本为 vue-cli@2.8.1,启用项目后,将以下 js 文件和 vue 文件放置在相应的目录中运行。
main.js
import Vue from 'vue'
import App from './App'
new Vue({
el: '#app',
template: '
components: { App }
})main.js 导入 App 组件,并在 components 中注册 App 组件。
App.vue
import TreeFolder from './components/tree-folder'
export default {
data: function () {
return {
folders: [
{name: 'folder1',
children: [{
name: 'folder1 - folder1',
children: [{
name: 'folder1 - folder1 - folder1'
}, {
name: 'folder1 - folder2',
children: [{
name: 'folder1 - folder2 - folder1'
}, {
name: 'folder1 - folder2 - folder2'
},
{name: 'folder 2',
children: [{
name: 'folder2 - folder1',
children: [{
name: 'folder2 - folder1 - folder1'
}, {
name: 'folder2 - folder2',
children: [{
name: 'folder2-content1'
},
{name: 'folder 3',
children: [{
name: 'folder3 - folder1',
children: [{
name: 'folder3 - folder1 - folder1'
}, {
name: 'folder3 - folder2',
children: [{
name: 'folder3-content1'
}},
components: {
TreeFolder
App 组件导入 TreeFolder 组件,并在 components 中注册 TreeFolder 组件。
components/tree-folder.vue
{{ folder.name }}
// 文档:「在我们的例子中,将 tree-folder 组件做为切入起点。我们知道制造矛盾的是 tree-folder-contents 子组件,所以我们在 tree-folder 组件的生命周期钩子函数 beforeCreate 中去注册 tree-folder-contents 组件」
export default {
props: ['folder'],
data: function () {
return {}
},
beforeCreate: function () {
// 文档给出的是require
// this.$optionsponents.TreeFolderContents = require('./tree-folder-contents.vue')
// 在基于vue-cli@2.8.1按照上面的写法还是会报错
// Failed to mount component: template or render function not defined.
// 所以我们应该改为基于es6的写法异步加载一个组件如下
this.$optionsponents.TreeFolderContents = () => import('./tree-folder-contents.vue')
TreeFolder 组件导入 TreeFolderContents 组件,并在 components 中注册 TreeFolderContents 组件。
components/tree-folder-contents.vue
{{ child.name }}
import TreeFolder from './tree-folder'
export default {
props: ['children'],
components: {
TreeFolder
TreeFolderContents 组件又导入 TreeFolder 组件,并在 components 中注册 TreeFolder 组件,产生了循环引用。
上面是我整理给大家的,希望今后会对大家有帮助。
相关文章:
在Node.js中如何搭建小程序后台服务
在js中有关文件加载优化方面的问题
使用nodejs+mongodb+vue如何配置ueditor
Vue组件的使用
'title': '无缝滚动第八行无缝滚动第八行',通过ref来获取页面上的dom
若在一个组件<>中添加上ref,那么获取到的dom就是对应的组件,也就是可以获取到组件的引用。
可以获取到组件中定义的data数据
父组件传值给子组件通过属性来传。
过来的值赋值给定义的值,然后修改那个值
定义一个全局组件
父组件给子组件通过属性传递一些值,而子组件做的一些约束就是组件的参数校验
父组件要传一子组件通过触发来向父组件传值个名叫content的属性,而子组件刚好定义了content的prop,这个就是props特性
非props特性
例如:给子组件的标签中定义一个click
上面的实现是错误的,原因就是在子组件中定义的@click中的click是的自定义的名称,它是接收子组件触发的名称,如:this.$emit('click'),@click是接收这样的的,并不是我们熟知的点击
实现上面的例子
在click中添加.native就可标明为原生
方法一,使用Vuex
方法二,使用发布模式,也称为总线机制
怎么使父组件给子组件优雅的传递dom,例如父组件要给子组件传递
Dell
按以往的方法应该是
使用slot可以解决问题
如果template中有多个
可以通过名称来确定对应的dom,如
通过动态组件来怎么实现呢
切换的时候,每次都是先销毁,然后再创建子组件,每次切换都销毁和创建
v-once就是为了避免这种情况的发生,使用v-once次展示的时候,会将组件放到内存中,第二次就不需要创建组件了,可以直接从内存中读取到
参考
Vue.js API文档
慕课网:Vue2.5开发去哪儿网App 从零基础入门到实战项目
vue更新或者重新加载组件方法
'date': '2017-12-16'分享vue更新组件三种方法,vue版本为2.6.10
对于单个组件,想自己灵活控制的情况下可以使用 v-if,设置 showModal 的值为true(方法一:加载)或者false(卸载)。
对于在列表中使用的组件,可以使用:key,组件id变化可以触发重新加载组件,我这边的例子使用的是时间戳
对于数据更新ui没有更新的情况下可以使用this.$forceUpdate
怎样进行Vue拖拽组件开发
};为什么选择Vue?
主要原因:对于前端开发来说,兼容性是我们必须要考虑的问题之一。我们的项目不需要兼容低版本浏览器。项目本身也是一个数据驱动型的。加之,Vue本身具有以下主要特性:
?使用虚拟DOM;
?轻量级框架;
?高效的数据绑定;
?灵活的组件系统;
?完整的开发生态链。
这就是我们为什么选择Vue框架的一些原因。
为什么要封装成一个Vue组件?
主要目的是可提高代码的复用性和可维护性。
?复用性:组件化后,一些样式和逻辑均通过配置参数的方式去异化体现,所以参数的可配置性提高了组件的复用率和灵活性。
?可维护性:组件化后,组件内部的逻辑只对组件负责,外部的逻辑只通过配置参数适配,所以提高了代码的逻辑清晰度,可以快速定位代码出现问题的地方。
组件化搭建页面图示:
上图可看出,在Vue中,所谓组件化搭建页面,简单来说,页面实际上是由一个个功能的组件搭建而成。这些组件之间可以组合、嵌套,最终形成了我们的页面。
组件构成
下面是一个完成的组件构成:
// 组件内模板
// 组件内逻辑代码
// 组件内封装的样式
开发Vue移动拖拽组件为例
拖拽原理
手指在移动的过程中,实时改变元素的位置即top和left值,使元素随着手指的移动而移动。
拖拽实现
?开始拖动时:获取到接触点相对于整个视图区的坐标clientX,clientY;获取元素距离视图上侧和左侧的距离 initTop,initLeft;计算接触点距离元素上侧和左侧的距离 elTop = clientY - initTop, elLeft = clientX - initLeft;
?拖动过程中:通过 currTop = clientY - elTop, currLeft = clientX - elLeft实时获取元素距离视图上侧和左侧的距离值,并赋值给元素,使元素跟着手指的移动而动起来;
?拖动结束,定位元素。
Vue中的实现
使用Vue,的不同之处是我们几乎不去作DOM,要充分利用Vue的数据驱动来实现拖拽功能。本例中,我们只需在垂直方向上拖动元素,所以只需考虑垂直方向的移动即可。
上图中,通过data中的dragList渲染拖拽区域列表,代码如下:
template:
拖拽可调整顺序
- {{.txt}}
script:
export default {
data() {
return {
dragList:null
}},
created() {
this.dragList = [
{isDrag: false,
txt: '列表1',
isShow: false
}...
]},
}设我们将元素从位置1拖至位置3,本质上是数组的顺序发生了改变。这就有必要提一下Vue的特性:数据驱动。
所谓的数据驱动就是当数据发生变化时,通过修改数据状态,使用户界面发生相应的改变,开发者不需要手动的去修改DOM。
Vue的数据驱动是通过MVVM这种框架来实现的,MVVM框架主要包含3个部分:Model、View、Viewmodel。
_ Model:数据部分;
_ View:视图部分;
_ Viewmodel:连接视图与数据的中间件。
_ oldIndex:元素在数组中的初始索引index;
_ elHeight:单个元素块的高;
_ currTop = clientY - elTop:元素在拖动过程中距离可视区上侧距离;
_ currTop - initTop > 0:得知元素是向上拖拽;
_ currTop - initTop < 0:得知元素是向下拖拽。
我们以向下拖拽来说:
_ 首先,我们要在拖拽结束touchend中判断元素从拖动开始到拖动结束时拖动的距离。若小于某个设定的值,则什么也不做;
_ 然后,在touchmove中判断,若(currTop - initTop) % elHeight>= elHeight/2成立,即当元素拖至另一个元素块等于或超过1/2的位置时,即可将元素插入到的位置为newIndex = (currTop - initTop) / elHeight + oldIndex。
写到这里,我们俨然已经用Vue实现了移动端的拖拽功能。但是拖拽体验并不好,接下来,我们对它进行优化。
优化点:我们希望,在元素即将可能落到的位置,提前留出一个可以放得下元素的区域,让用户更好的感知拖拽的灵活性。
方案:(方案已被验证是可行的)将li的结构做一下修改,代码如下:
// 向上拖拽时留空
{{.txt}}
// 向下拖拽时留空
?拖拽过程中:将元素即将落入新位置的那个li下p的.isShow设置为true,其他li下p的.isShow均设置为false;
?拖拽结束:将所有li下p的.isShow 均设置为false,将元素定位方式由absolute设置为static。
贴一段伪代码:
touchStart(e){
// 获取元素距离视口顶部的初始距离
initTop = e.currentTarget.offsetTop;
// 开始拖动时,获取鼠标距离视口顶部的距离
initY = e.touches[0].clientY;
// 计算出接触点距离元素顶部的距离
elTop = e.touches[0].clientY - initTop;
},
touchMove(index, , e){
// 将拖拽结束时,给元素设置的static定位方式移除,防止元素二次拖拽无效
e.target.classList.remove('static');
// 给拖拽的元素设置定位方式
e.target.classList.add('ab');
// 获取元素在拖拽过程中距离视口顶部距离
currTop = e.touches[0].clientY - elTop;
// 元素在拖拽过程中距离视口顶部距离赋给元素 = currTop ;
// 获取元素初始位置
oldIndex = index;
// 获取拖拽元素
currItem = ;
// 若元素已经拖至区域外
if(e.touches[0].clientY > (this.dragList.length) elHeight){
// 将元素距离上侧的距离设置为拖动区视图的高
currTop = (this.dragList.length) elHeight;
return;
}// 向下拖拽
if(currTop > initTop ){
// 若拖拽到大于等于元素的一半时,即可将元素插入到的位置
if((currTop - initTop) % elHeight>= elHeight / 2){
// 计算出元素拖到的位置
newI}}ndex = Math.round((currTop - initTop) / elHeight) + index;
// 确保新元素的索引不能大于等于列表的长度
// 将所有列表留空处隐藏
for(var i = 0;i< this.dragList.length;i++){
this.dragList[i].isShow = false;
}// 将元素即将拖到的新位置的留空展示
this.dragList[newIndex].isShow = true;
}else {
return;
}// 向上拖拽,原理同上
if(currTop < initTop){ ... } }, touchEnd(e){ // 若拖动距离大于某个设定的值,则按照上述,执行相关代码 if(Math.abs(e.changedTouches[0].clientY - initY ) > customVal){
this.dragList.spl(oldIndex, 1);
this.dragList.spl(newIndex, 0, currItem);
for(var i = 0;i< this.dragList.length;i++){
this.dragList[i].isShow = false;
this.dragList[i].isShowUp = false;
e.target.classList.remove('ab');
e.target.classList.add('static');
}优化后,如下图所示:
以上便是用Vue实现移动端拖拽组件的过程。我们知道,有些项目是需要在PC端用Vue实现此功能。这里简单提一下PC与移动端的区别如下:
?PC端可以使用的组有两种:种:H5新特性draggable,dragstart,drag,dragend;第二种:mousedown,mousemove,mouseup;
?PC端获取鼠标坐标是通过e.clientX,clientY,区别于移动端的e.touches[0].clientX,e.touches[0].clientY。
相信看了本文案例你已经掌握了方法,更多精彩请关注Gxl网其它相关文章!
阅读:
怎样作vue中$emit 与$on父子与兄弟组件通信
如何使用node命令方式启动修改端口
声明:本站所有文章资源内容,如无特殊说明或标注,均为采集网络资源。如若本站内容侵犯了原著者的合法权益,可联系 836084111@qq.com 删除。