[译]怎样在Vue.js中使用jquery插件
原文:http://gambardella.info/2016/09/05/guide-how-to-use-vue-js-with-jquery-plugins
使用Vue真的太棒了,但是也有可能使你头疼,当你试图使它与jquery插件混用的时候。
问题的原因是jquery与Vue是完全不同的东西,Vue是通过组件与数据绑定来进行渲染的,jquery则主要是用来做简单的单击处理和强大的操纵DOM的能力。
我试图寻找一些东西来帮助自己解决这个问题,但是我发现一些组件所做的工作不是很让我满意,所以让我告诉你怎样使Vue与jquery插件混用。
这么做的目的是什么?
大多数情况下你能使用jquery和一些简单的Vue来满足你的需求,Modals, sliders等等和一些Vue组件结合起来是很快的。
所以我们的目标是用强大的jQuery插件与Vue快速结合。
我们将...
- 用Vue的自定义指令来构建jquery
- 当元素生成时初始化插件
- 当元素撤销时销毁插件
- 发送事件来通知组件
- 从组件接收事件并将它们传递给插件
教程时间
我选择Fengyuan Chen’s的cropper因为它是一个很棒的jQuery插件,如果时间限制在60分钟之内的话你肯定不可能重写这个插件在不使用Vue的情况下。
DEMO:https://vue-jquery-cropper-demo.firebaseapp.com/
我将从最开始来演示,如果你已经完成请跳过这个部分。
创建项目
# install vue-cli
$ npm install -g vue-cli
# create a new project using the "webpack" boilerplate
$ vue init webpack vue-cropper ? Project name "vue-cropper"
? Project description "A Vue.js project"
? Author "Christian Gambardella <christian@gambardella.info>"
? Use ESLint to lint your code? "Yes"
? Pick an ESLint preset "Standard"
? Setup unit tests with Karma + Mocha? "No"
? Setup e2e tests with Nightwatch? "No" $ cd vue-cropper
$ npm install
祝贺你已经有了一个Vue的项目。
安装 jQuery 和 cropper.js
# install jQuery & cropper
$ npm install jquery cropper --save
为jquery和Vue自定义指令配置webpack
为webpack配置添加jquery和Vue自定义指令的映射。
通常webpack已经引入了完整的jquery版本,但还是建议再一次引入一下。
您可以看到Vue的webpack模板已经添加到组件的文件夹中。我通常会添加很多其他文件夹像自定义指令,mixin等等。在这个例子中,我们只添加了自定义指令。
这将帮助我们引入依赖关系而无需知道其确切的路径。这也是有益的在你重构你的应用的时候。你也并不需要管理相对路径。
把下面高亮部分添加到build/webpack.base.conf文件中。
resolve: {
extensions: ['', '.js', '.vue'],
fallback: [path.join(__dirname, '../node_modules')],
alias: {
'src': path.resolve(__dirname, '../src'),
'assets': path.resolve(__dirname, '../src/assets'),
'components': path.resolve(__dirname, '../src/components'),
'jquery': path.resolve(__dirname, '../node_modules/jquery/src/jquery'),
'directives': path.resolve(__dirname, '../src/directives')
}
},
不要忘了在末尾添加逗号。
准备应用组件
我要开始使用组件,因为我相信这是更容易理解的,漂亮和简单的组件。如果你已经知道如何在组件中使用它们那么就可以立即写这个指令来实现它们。
替换src/App.vue文件的template部分
<template>
<div id="app">
<img
v-cropper="cropOptions"
src="https://i.imgur.com/WcvkCxl.png"
alt="jQuery Meme">
</div>
</template>
替换src/App.vue文件的script部分
<script>
import Cropper from './directives/Cropper' export default {
directives: {
Cropper
}, data () {
return {
cropOptions: {
viewMode: 0,
zoomable: false
}
}
}
}
</script>
一些需要重点注意的地方
- 我们引入jQuery也不需要处理组件的初始化。
- 把Cropper的设置选项当做原始绑定数据。
- Cropper将在初始化时渲染,再销毁时使其消失。
- 组件的名字可以在template用作标签使用,MyCropper转变为my-cropper。
- 对它进行初始化时,我们必须添加v-my-cropper元素在组件的模板里。
创建Cropper组件
这是本教程的核心。我们要创建一个Cropper指令来处理低层代码的DOM操作。在这种情况下我们要初始化Cropper。
自定义指令是用来提供一种机制来映射数据并任意操作DOM的行为。
创建src/directives/Cropper.js
import jQuery from 'jquery'
import 'cropper' export default {
deep: true, bind () {}, update (options) {
// Destroy in case it has been initialized already.
jQuery(this.el).cropper('destroy')
// Initializing directly after destroying
// didn't work. Wrapping it in a setTimeout
// seems to do the trick.
setTimeout(() => {
jQuery(this.el).cropper(options)
}, 0)
}, unbind () {
jQuery(this.el).cropper('destroy')
}
}
每一个Vue自定义组件的最核心部分是其提供可以用来绑定,更新,解绑相应方法。
- bind:当元素在文档中生成时只触发一次。
- update:当bind方法触发后和绑定数据改变时触发,在这种情况下cropOptions只是一个对象。Vue.js自定义指令需要知道如果它的相关属性也是一个对象。这就是为什么我们需要添加deep: true在这种情况下。
- unbind:当DOM元素被移除时触发,在这个方法里可以销毁组件并且移除监听的事件。
在Vue 2中会有些许变化。
vm实例被作为函数参数传递,不会被设置为this。
指令的update方法只能在数据改变后触发而不会在bind方法之后触发。
第一次运行
这是我们所能做的最小限度,让我们运行起来看看如何。
这是很快做出来的,所以我们并没有添加cropper的样式,让我们添加并再一次运行。
先添加高亮部分在src/main.js文件中
import '../node_modules/cropper/dist/cropper.css'
import Vue from 'vue'
import App from './App' /* eslint-disable no-new */
new Vue({
el: 'body',
components: { App }
})
启动服务
$ npm run dev
当所有事情都做好后,你应该看到一个图片和一个cropbox并且可以使其移动。

切换 on/off
从现在起一切都会很简单。我们将通过这个案件。使每件事都会简单起来。
我们用一个按钮来启用和禁用cropper。页面开始用户选择一个文件切换为cropper的打开状态。证明了cropper可以在任何时候被初始化。
编辑src/App.vue的script部分
import Cropper from './directives/Cropper'
export default {
directives: {
Cropper
},
data () {
return {
cropOptions: {
viewMode: 0,
zoomable: false
},
showCropper: false
}
},
methods: {
toggleCropper () {
this.showCropper = !this.showCropper
}
}
}
- data中添加showCropper: false
- 添加一个切换方法toggleCropper
编辑src/App.vue的template部分
<div id="app">
<button id="toggle" @click="toggleCropper">Toggle Cropper</button>
<img
v-if="showCropper"
v-cropper="cropOptions"
src="https://i.imgur.com/WcvkCxl.png"
alt="Mustache">
</div>
- 添加一个按钮绑定@click
- 在img标签上添加v-if指令
每一次图像的显示都会调用自定义cropper指令的bind和update方法。
当showCropper设置为false时,cropper的unbind将被调用。
这里不会使我们陷入困境。
cropper将被加载在用户需要时和卸载后。
改变选项
我们已经拥有需要更新cropper的选项。如果我们有一个现有jQuery插件,并且会接收新选项,我们将不需要销毁当前实例来重新创建插件实例。不幸的是cropper不允许这样。
让我们添加一个开关来控制图像缩放。
编辑src/App.vue的template部分
<div id="app">
<button id="toggle" @click="toggleCropper">Toggle Cropper</button>
<img
v-if="showCropper"
v-cropper="cropOptions"
src="https://i.imgur.com/WcvkCxl.png"
alt="Mustache">
<input id="zoomable" type="checkbox" v-model="cropOptions.zoomable">
<label for="zoomable">Zoomable?</label>
</div>
很简单,对吗?
通过指令获取数据
cropper有一个回调方法,当我们触发一个事件时将会调用这个方法。
编辑src/directives/Cropper.js
import jQuery from 'jquery'
import 'cropper' export default {
deep: true, bind () {}, update (options) {
options.crop = (event) => {
this.vm.$emit('crop', event)
}
// Destroy in case it has been initialized already.
jQuery(this.el).cropper('destroy')
// Initializing directly after destroying
// didn't work. Wrapping it in a setTimeout
// seems to do the trick.
setTimeout(() => {
jQuery(this.el).cropper(options)
}, 0)
}, unbind () {
jQuery(this.el).cropper('destroy')
}
}
编辑App组件的script部分来处理crop事件
import Cropper from './directives/Cropper'
export default {
directives: {
Cropper
},
data () {
return {
cropData: {},
cropOptions: {
viewMode: 0,
zoomable: false
},
showCropper: false
}
},
events: {
crop (event) {
this.cropData = {
x: event.x,
y: event.y,
width: event.width,
height: event.height
}
}
},
methods: {
toggleCropper () {
this.showCropper = !this.showCropper
}
}
}
编辑App组件的template部分来展示crop数据
<template>
<div id="app">
<button id="toggle" @click="toggleCropper">Toggle Cropper</button>
<img
v-if="showCropper"
v-cropper="cropOptions"
src="https://i.imgur.com/WcvkCxl.png"
alt="Mustache">
<input id="zoomable" type="checkbox" v-model="cropOptions.zoomable">
<label for="zoomable">Zoomable?</label>
<pre id="output">
x: {{ cropData.x }}
y: {{ cropData.y }}
width: {{ cropData.width }}
height: {{ cropData.height }}
</pre>
</div>
</template>
正如您所看到的我选择从指令来发出事件来监听App组件。问问自己为什么选择这么做。我也可以选择在App组件上面创建一个方法,将其绑定到cropper的监听器中。
反模式。options.crop = this.vm.handleCrop
操作其他action
最后使事件从一个组件流向一个指令来改变显示状态。我们要用它来调用cropper的action。让我告诉你我将如何添加一个按钮来控制图片旋转。
编辑App组件的temlpate部分并添加一个控制图片旋转的按钮
<template>
<div id="app">
<button id="toggle" @click="toggleCropper">Toggle Cropper</button>
<img
v-if="showCropper"
v-cropper="cropOptions"
src="https://i.imgur.com/WcvkCxl.png"
alt="Mustache">
<input id="zoomable" type="checkbox" v-model="cropOptions.zoomable">
<label for="zoomable">Zoomable?</label>
<button @click="$emit('rotate', 90)">Rotate 90°</button>
<pre id="output">
x: {{ cropData.x }}
y: {{ cropData.y }}
width: {{ cropData.width }}
height: {{ cropData.height }}
</pre>
</div>
</template>
编辑src/directives/Cropper.js添加用来监听和解绑的事件
import jQuery from 'jquery'
import 'cropper' export default {
deep: true, bind () {
this.vm.$on('rotate', (deg) => {
jQuery(this.el).cropper('rotate', deg)
})
}, update (options) {
options.crop = (event) => {
this.vm.$emit('crop', event)
}
// Destroy in case it has been initialized already.
jQuery(this.el).cropper('destroy')
// Initializing directly after destroying
// didn't work. Wrapping it in a setTimeout
// seems to do the trick.
setTimeout(() => {
jQuery(this.el).cropper(options)
}, 0)
}, unbind () {
jQuery(this.el).cropper('destroy')
this.vm.$off('rotate')
}
}
摘要
Et voilà you’re done!
这样做的美妙之处在于,指令是用来解耦组件并在多个组件中使用,它会自动初始化并附加到DOM元素中,在DOM被移除之前销毁。
我希望你会喜欢这篇文章,如果你有问题和建议,可随时给我发消息或评论文章。
Best,
Christian
[译]怎样在Vue.js中使用jquery插件的更多相关文章
- Vue项目中使用jquery插件
1.引入jquery,并且在vue.config.js里配置 config.plugin('provide') .use(webpack.ProvidePlugin, [{ $: 'jquery', ...
- Vue.js中使用select选择下拉框
在Vue.js中使用select选择下拉框有两种方法: 第一种: Add.html: <select v-model="sysNotice.noticeType" id=&q ...
- 在vue项目中引入jquery
在vue项目中引入jquerycnpm install jquery --save在main.js中引入,加入下面这行代码:import 'jquery'注:有些项目是按需加载的,在main.js里面 ...
- vue-cli3搭建的vue项目中使用jquery
装包:npm install jquery --save 方式一 全局使用 1)main.js中引入 // jquery import $ from 'jquery' Vue.prototype.$ ...
- vue.js中,input和textarea上的v-model指令到底做了什么?
v-model是 vue.js 中用于在表单表单元素上创建双向数据绑定,它的本质只是一个语法糖,在单向数据绑定的基础上,增加了监听用户输入事件并更新数据的功能: 对,它本质上只是一个语法糖,但到底是一 ...
- 实例分析Vue.js中 computed和methods不同机制
在vue.js中,有methods和computed两种方式来动态当作方法来用的 1.首先最明显的不同 就是调用的时候,methods要加上() 2.我们可以使用 methods 来替代 comput ...
- vue.js 中双向绑定的实现---初级
1. 1 我们看到的变量,其实都不是独立的,它们都是windows对象上的属性 <!DOCTYPE html> <html lang="en"> <h ...
- Vue组件中引入jQuery
一.安装jQuery依赖 在使用jQuery之前,我们首先要通过以下命令来安装jQuery依赖: npm install jquery --save # 如果你更换了淘宝镜像,可以使用cnpm来安装, ...
- 浅析Vue.js 中的条件渲染指令
1 应用于单个元素 Vue.js 中的条件渲染指令可以根据表达式的值,来决定在 DOM 中是渲染还是销毁元素或组件. html: <div id="app"> < ...
随机推荐
- 如何给apk文件签名
1.签名的意义 为了保证每个应用程序开发商合法ID,防止部分开放商可能通过使用相同的Package Name来混淆替换已经安装的程序,我们需要对我们发布的APK文件进行唯一签名,保证我们每次发布的版本 ...
- New Year and Domino 二维前缀和
C. New Year and Domino time limit per test 3 seconds memory limit per test 256 megabytes input stand ...
- C#学习之泛型
//主函数//主函数里面调用的类都在后面有具体描述 using System; using System.Collections.Generic; using System.Linq; using S ...
- ACM2112迪克斯特算法
HDU Today Problem Description 经过锦囊相助,海东集团终于度过了危机,从此,HDU的发展就一直顺风顺水,到了2050年,集团已经相当规模了,据说进入了钱江肉丝经济开发区50 ...
- vue2路由之指定滑动位置scrollBehavior
看源码的时候看到这个属性: 新手自然不知道这个是什么东西了,查了下vue API: https://router.vuejs.org/en/advanced/scroll-behavior.html ...
- [洛谷P1404] 平均数
洛谷题目链接:平均数 题目描述 给一个长度为n的数列,我们需要找出该数列的一个子串,使得子串平均数最大化,并且子串长度>=m. 输入输出格式 输入格式: N+1行, 第一行两个整数n和m 接下来 ...
- [Luogu 2580] 于是他错误的点名开始了
[Luogu 2580] 于是他错误的点名开始了 不用好奇我为什么突然发水题题解- 突然觉得自己当年的幼儿园码风太幼稚,就试图把数据结构什么的用指针重写一遍- 想当年因为空间开太大而全 RE,调了一下 ...
- 原生js addclass,hasClass,removeClass,toggleClass的兼容
(function (window) { 'use strict'; // class helper functions from bonzo https://github.com/ded/bonzo ...
- 利用forEach循环Dom元素…
大家都知道forEach是循环数组用的,而且很方便,可以丢掉for循环了,但是它不能循环Dom元素.其实我们可以利用call来完成forEach循环Dom; 假设有这样的HTML结构: <ul ...
- bigDecimal学习
1.引言 float和double类型的主要设计目标是为了科学计算和工程计算.他们执行二进制浮点运算,这是为了在广域数值范围上提供较为精确的快速近似计算而精心设计的.然而,它们没有提供完全精确的结果, ...