Vue的异构

news/2024/5/22 17:51:01

Vue的异构

组件化是至上而下的,一旦一个页面从某个Dom节点开始逐渐话之后,相当于从这个Dom节点开始所有的子辈节点都被组件化框架所接管了,这是因为Vue或React这类组件化框架都有一个重要的特性:那就是 数据=》视图 的一一对应关系,所以在被组件化框架所接管的区域内,所以的Dom操作都应该有组件化框架来完成,如果中间有其他的Dom操作,比如jQuery修改Dom节点元素,会破坏 数据=》视图 这个一一对应关系。

但是事实上,我们有大量的网页系统和框架并不是基于组件化框架所搭建的,所以很多时候我们必须拿出异构的方案。这里的异构指的是 组件化框架和其他框架共存的情况。

我们主要介绍Vue异构方法,实际上Vue提供的computed、watch 、directive等对异构提供了很大的帮助。所以Vue的异构相对其他组件化框架来说更加容易理解和操作。

组件化异构的核心思想就是在不破坏 数据=》视图 的前提下,将非组件化的代码封装成类组件化的代码。

不属于异构的情况

在列举Vue的异构方法之前,我们要分清楚什么情况才称之为异构,并不是引入了任意js库就叫异构。只有引入其他js库,并且我们使用该库去操作Vue所接管的Dom节点时才称之为异构。

一个不是异构的例子

我们从github上下载Vue的源代码,里面有一些实用的例子在example文件夹里,其中有一个《elastic-header》的例子,我们能看到这个例子里引用了dynamic.js这个js库来实现平滑的动画效果。那这里面算不算异构能,需不需要我们采取什么特殊处理呢?会不会破坏 数据=》视图 的映射关系呢?其实是不会的!
Alt text
我们看这里面使用dynamics.js的方法,dynamics被当成一个工具库来使用,并没有直接操作Dom,而是改变Vue里面对象的数值,最终是由Vue去操作Dom,所以并不会破坏 数据=》视图 的映射关系,所以我们并不需要担心引入这类的库与Vue混用会产生问题。

下面我们对Vue的异构方法做一些分类,不同的异构需求关注的重心也不太一样。

通过封装成Vue组件的方式实现异构

在Vue的example库里就有一个Vue异构的例子,在example/select2这个目录下。这个例子是Vue与jQuery的插件select2进行异构的例子 ,并且是通过将select2封装成Vue组件的方式实现异构的。

<!DOCTYPE html>
<html lang="en"><head><meta charset="utf-8"><title>Vue.js wrapper component example (jquery plugin: select2)</title><!-- Delete ".min" for console warnings in development --><script src="../../dist/vue.min.js"></script><script src="https://unpkg.com/jquery"></script><script src="https://unpkg.com/select2@4.0.3"></script><link href="https://unpkg.com/select2@4.0.3/dist/css/select2.min.css" rel="stylesheet"><style>html, body {font: 13px/18px sans-serif;}select {min-width: 300px;}</style></head><body><div id="el"></div><!-- using string template here to work around HTML <option> placement restriction --><script type="text/x-template" id="demo-template"><div><p>Selected: {{ selected }}</p><select2 :options="options" v-model="selected"><option disabled value="0">Select one</option></select2></div></script><script type="text/x-template" id="select2-template"><select><slot></slot></select></script><script>Vue.component('select2', {props: ['options', 'value'],template: '#select2-template',mounted: function () {var vm = this$(this.$el).val(this.value)// init select2.select2({ data: this.options })// emit event on change..on('change', function () {vm.$emit('input', this.value)})},watch: {value: function (value) {// update value$(this.$el).val(value).trigger('change')},options: function (options) {// update options$(this.$el).select2({ data: options })}},destroyed: function () {$(this.$el).off().select2('destroy')}})var vm = new Vue({el: '#el',template: '#demo-template',data: {selected: 1,options: [{ id: 1, text: 'Hello' },{ id: 2, text: 'World' }]}})</script></body>
</html>

这里面最关键的代码就是 组件的mounted方法和watch方法,异构最关键的事情有三件

  • Vue要初始化其他库(组件化异构的时候一般在mounted方法里,因为这个时候能拿到Dom元素)
  • 当Vue数据发生变化的时候要调用其他库的方法更新页面
  • 当其他库的数据方法发生变化的时候要对Vue中的数据重新赋值,保证 数据=》视图这个对应关系不变
$(this.$el).val(this.value)// 在mounted方法里初始化 select2库.select2({ data: this.options })// 当其他库的数据方法发生变化的时候要对Vue中的数据重新赋值,保证 数据=》视图这个对应关系不变.on('change', function () {vm.$emit('input', this.value)})
watch: {// 当Vue数据发生变化的时候要调用其他库的方法更新页面value: function (value) {// update value$(this.$el).val(value).trigger('change')},options: function (options) {// update options$(this.$el).select2({ data: options })}},

通过directive的方式实现异构

下面我们将官方提供的例子修改一下,改成由 directive的方式来实现异构。因为指令在Vue2里能力已经被极大的削弱,但也依然具备能够实现异构的能力

<!DOCTYPE html>
<html lang="en">
<head><meta charset="utf-8"><title>Vue.js wrapper component example (jquery plugin: select2)</title><!-- Delete ".min" for console warnings in development --><script src="../../dist/vue.min.js"></script><script src="https://unpkg.com/jquery"></script><script src="https://unpkg.com/select2@4.0.3"></script><link href="https://unpkg.com/select2@4.0.3/dist/css/select2.min.css"rel="stylesheet"><style>html, oubody {font: 13px/18px sans-serif;}select {min-width: 300px;}</style>
</head>
<body><div id="el"></div><!-- using string template here to work around HTML <option> placement restriction -->
<script type="text/x-template"id="demo-template"><div><p>Selected: {{ selected }}</p>// 使用v-select指令<select v-select="{options:options,onChange:onChange,value:selected}"></select></div>
</script><script>Vue.directive('select', {// 当绑定元素插入到 DOM 中。bind: function (el, value) {console.log('bind ' + arguments);},inserted: function (el, binding) {var value = binding.value// 聚焦元素$(el).val(value.value)// init select2.select2({data: value.options})// emit event on change..on('select2:select', function (evt) {var id = evt.params.data.idvalue.onChange(id)})console.log('inserted ' + arguments);},update: function (el, binding) {var val = $(el).val()var value = binding.value.valueif (val !== value) {$(el).val(value).trigger('change')}},componentUpdated: function () {console.log('componentUpdated ' + arguments);},unbind: function () {console.log('unbind ' + arguments);}})var vm = new Vue({el: '#el',template: '#demo-template',data: {selected: 1,options: [{id: 1,text: 'Hello'},{id: 2,text: 'World'}]},methods: {onChange: function (val) {debugger;this.selected = val}}})
</script>
</body>
</html>

因为指令无法直接获取到vm,所以我们通过binding里传入onChange方法来更改组件的值。

这里面最关键的代码就是指令的inserted方法和update方法

  • 指令要初始化其他库(在inserted方法里,因为这时候能获取到对应的Dom节点)
  • 当Vue数据发生变化的时候要调用其他库的方法更新页面 (在update方法里调用select2库的更新方法)
  • 当其他库的数据方法发生变化的时候要对Vue中的数据重新赋值,保证 数据=》视图这个对应关系不变(注册事件监听,调用指令的binding.value值里的onChange方法)

循环嵌套Vue组件

想象中很复杂的异构其实只要把数据到视图的逻辑都理清楚,其实实现起来非常容易。

我们在想象一个应用场景,如果这时候需要在select2这个jQuery插件库中再插入 Vue组件应该怎么处理呢?

首先在由其他库中生成的Dom节点中插入Vue组件,只能通过 new Vue()方法去重新初始化Vue组件。但是需要注意一点的是组件是一个可以多实例的概念,所以我们不能简单的给嵌套Vue组件一个Id,因为当多实例的情况下通过这个Id能取到不只一个Dom节点,所以我们最佳方式是通过Dom节点树向下寻找,直到找到具体拿来初始化的对应元素,可以通过 jQuery 的 find方法,也能通过生成 uuid的方式来生成唯一的Id,通过这些方式来保证组件在多实例的情况下运行起来也不会出现问题。


http://lihuaxi.xjx100.cn/news/240881.html

相关文章

浙江大学软件学院2020年保研上机模拟练习 7-2 Distance of Triples

思路一&#xff1a; 3个数组都按照小到大排序&#xff0c;设置3个指针&#xff0c;起始都在数组的末尾&#xff0c;如果1个指针向前移动1位可以让对应元素和另两个数组元素的距离之和减小&#xff0c;则移动它。如果某一回合三个指针都没动&#xff0c;就跳出循环。 非满分&a…

oracle 查询重复数据并且删除, 只保留一条数据

数据库操作中&#xff0c;经常会因为导数据造成数据重复&#xff0c;需要进行数据清理&#xff0c;去掉冗余的数据&#xff0c;只保留正确的数据 一&#xff1a;重复数据根据单个字段进行判断 1、首先&#xff0c;查询表中多余的数据&#xff0c;由关键字段&#xff08;name&am…

《C++游戏编程入门(第4版)》——1.12 习题

本节书摘来自异步社区出版社《C游戏编程入门&#xff08;第4版&#xff09;》一书中的第1章&#xff0c;第1.1节&#xff0c;作者&#xff1a;【美】Michael Dawson&#xff08;道森&#xff09;&#xff0c;更多章节内容可以访问云栖社区“异步社区”公众号查看。 1.12 习题 C…

1021 Deepest Root

要解决两大问题&#xff1a; 1. 数包含几个连通分量 2. 如何找到最深结点 注意&#xff1a;connected components的意思是连通分量 问题1我用并查集解决 问题2转化为如何得到每个结点的深度 值得注意之处是对于问题2来说&#xff0c;下图是测试用例1给出的树 可以看出从1…

consul安装配置使用

2019独角兽企业重金招聘Python工程师标准>>> 环境 centos:7.3 docker:1.12.6 kernel:3.10.0-514.6.1.el7.x86_64 consul:0.8.1 server1:10.1.13.221 server2:10.1.13.222 consul的功能 服务发现 健康检查 支持多数据中心 key/value存储 consul的使用场景 docker实例…

警惕!国内某广告SDK内置“后门”功能,Google Play商店已强制下架

本文讲的是警惕&#xff01;国内某广告SDK内置“后门”功能&#xff0c;Google Play商店已强制下架&#xff0c;新闻摘要 Lookout安全团队近日发现了个信的广告软件开发工具包&#xff08;SDK&#xff09;&#xff0c;可以通过下载恶意插件&#xff0c;借助其他合法app对用户实…

java 冒泡排序和快速排序 实现

面试的时候经常会遇到面试官让你直接手写排序算法&#xff0c;下面是冒泡排序和快速排序的实现。冒泡排序基本流程就是&#xff0c;自下而上比较相邻的两个元素进行比较&#xff0c;让大的元素往下面沉&#xff0c;较小的往上冒。按照排序规则进行比较&#xff0c;如果是跟排序…