草庐IT

javascript - 设置在另一个模块中实现的抽象的、实时可解析的 Vuex 存储?

coder 2024-05-12 原文

我有两个模块,我们称它们为coreimplementation .如何设置商店以启用 core 中的内容依赖 implementation 提供的假设商店?

implementation的商店我正在做这样的事情:

import Core from 'core'

export default new Vuex.Store(
    new Core().defaultStore
)

这将注册默认状态、突变、操作和 getter(该设置允许 implementation 的用户扩展/修改 core 提供的默认存储)。

问题出现在core 中的一个 Action 中当它尝试访问非 vue JS 文件中的 getter 时。

export default class SomeClassInCore {
    exampleMethod() {
        // The getters will not be accessible here!
        return store.getters.someKey
    }
}

有什么方法可以实现“主”存储的“运行时”解析吗?我在想我是否可以使用 window访问 implementation 创建的 Vue 实例 repo ?

我试过这样做

import store from './store.js'
import Vue from 'vue'
import { CoreVueTools } from 'core'

window.Vue = Vue
window.store = store

Vue.use(CoreVueTools)

new Vue({
    el: '#app',
    store
})

然后像这样访问它

exampleMethod() {
    return window.store.getters.someKey
}

这行得通,但我对这个解决方案不是很满意,一定有比依赖窗口更好的方法吧?我可以使用其他设计模式吗?

最佳答案

我不确定这是否符合您正在寻找解决方案的方向(因为它不依赖 vuex),如果不是,我希望它至少会是一个有趣的阅读 =)。 ..

Can I use another design pattern?

您可以尝试一种非常简单(但还不太为人所知)的方法来使用基于 Meiosis pattern 的方法来处理状态管理。 (Homepage)。我最近用一个 React 和一个 riot.js 应用程序实现了这个模式,与 redux 和 co 相比,它使用如此少的样板代码工作得非常好(除了作为流提供的东西之外没有依赖性,但你也可以自己实现它! ).我还没有机会用 vue 尝试它(在我的待办事项列表上),所以下面的代码只是从 repo 中的“设置”示例中快速(和减少)的剽窃。 ...

减数 split 模式的基本思想是依靠流来实现一个 react 循环,并将状态管理代码与 View 代码分开。模式的快速总结(取自主页):

  • 从初始状态开始。
  • 创建补丁更新流。
  • 补丁可以是 Patchinko 补丁、功能补丁或您自己的补丁。
  • 创建向更新流发布补丁的函数的操作对象。
  • 通过在具有初始状态的更新流上使用扫描和用于函数补丁的 (x, f) => f(x) 创建状态流。
  • 将状态和操作传递给 View 。

甚至可以在 SO 代码段中使用的东西 =):

(关键部分跳到这个答案的最后)

.row {
  padding-bottom: 0.5rem;
}

button {
  display: inline-block;
  padding: 0 1rem;
  color: #555;
  text-align: center;
  font-size: 0.75rem;
  font-weight: 600;
  line-height: 1.5rem;
  letter-spacing: 1px;
  text-transform: uppercase;
  text-decoration: none;
  white-space: nowrap;
  background-color: transparent;
  border-radius: 0.25rem;
  border: 1px solid #bbb;
  cursor: pointer;
  box-sizing: border-box;
}

button:hover,
button:focus{
  color: #333;
  border-color: #888;
  outline: 0;
}
<div id="app">
	<temp />
</div>

<script src="https://cdn.jsdelivr.net/npm/flyd/flyd.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.min.js"></script>
<script name="store">
	// for convenience, let's define an initial state
	const initialState = {
		temperature: {
			value: 22,
			unit: "C"
		}
	};
	
	// $update is a stream of patch functions
	// the patch function passed here is doing
	// nothing, it takes state and returns is,
	// just for consistency...
	const update = flyd.stream(state => state);
	
	// define another stream to accumulate patches
	// starting from the initial state
	const getState = flyd.scan(
		(state, patchFn) => patchFn(state),
		initialState,
		update,
	);
	
	// actions are functions that take an input
	// and pass an appropriate patch function
	// to the update stream
	const actions = {
		changeTemp: amount => update(state => ({
			...state,
			temperature: {
				...state.temperature,
				value: state.temperature.value + amount
			}
		})),
		changeTempUnit: () => update(state => ({
			...state,
			temperature: {
				...state.temperature,
				unit: state.temperature.unit === "C" ? "F" : "C",
				value: state.temperature.unit === "C"
					? Math.round((state.temperature.value * 9) / 5 + 32)
					: Math.round(((state.temperature.value - 32) / 9) * 5)
			}
		}))
	};
	
	// define global store by combining actions and getState
	const store = {
		getState,
		actions
	};
</script>

<script name="app">
	new Vue({
		el: "#app",
		components: {
			'temp': {
				data() {
					const initial = store.getState();
					return {
						temperature: initial.temperature.value,
						unit: initial.temperature.unit
					};
				},
				mounted() {
					store.getState.map(s => {
						this.temperature = s.temperature.value;
						this.unit = s.temperature.unit;
					});
				},
				methods: {
					incTemp() {
						store.actions.changeTemp(+1);
					},
					decTemp() {
						store.actions.changeTemp(-1);
					},
					changeUnit() {
						store.actions.changeTempUnit();
					}
				},
				props: [],
				template: `
					<div class="temp-component">
						<div class="row">
							<button @click="incTemp">+</button>&nbsp;
							<button @click="decTemp">&minus;</button>&nbsp;
							<span>The temperature is {{temperature}} &deg;{{unit}}</span>
						</div>
						<div class="row">
							<button @click="changeUnit">Change temperature unit</button>
						</div>
					</div>
				`
			}
		}
	});
</script>

该模式绝对独立于框架,因此无论您使用什么框架,商店的设置等都可以保持不变。 vue.js 的关键部分是我们如何将商店与 vue/vue-components 连接起来,例如这个:

data() {
    const initial = store.getState();
    return {
        temperature: initial.temperature.value,
        unit: initial.temperature.unit
    };
},
mounted() {
    store.getState.map(s => {
        this.temperature = s.temperature.value;
        this.unit = s.temperature.unit;
    });
},

首先,我们将部分全局状态数据(或整个全局状态)设置为组件的data() 函数的返回值。然后我们简单地使用 getState 流的 map 函数来更新组件状态。 .map() 是 getState 流的 react 函数(这里由 flyd 提供)。

PS:还要检查上面链接的示例 repo 以获得更复杂的示例,包括 todo-mvcrealworld(以及更多)。 .

关于javascript - 设置在另一个模块中实现的抽象的、实时可解析的 Vuex 存储?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56768055/

有关javascript - 设置在另一个模块中实现的抽象的、实时可解析的 Vuex 存储?的更多相关文章

  1. ruby - 使用 RubyZip 生成 ZIP 文件时设置压缩级别 - 2

    我有一个Ruby程序,它使用rubyzip压缩XML文件的目录树。gem。我的问题是文件开始变得很重,我想提高压缩级别,因为压缩时间不是问题。我在rubyzipdocumentation中找不到一种为创建的ZIP文件指定压缩级别的方法。有人知道如何更改此设置吗?是否有另一个允许指定压缩级别的Ruby库? 最佳答案 这是我通过查看ruby​​zip内部创建的代码。level=Zlib::BEST_COMPRESSIONZip::ZipOutputStream.open(zip_file)do|zip|Dir.glob("**/*")d

  2. ruby - 在 Ruby 中使用匿名模块 - 2

    假设我做了一个模块如下:m=Module.newdoclassCendend三个问题:除了对m的引用之外,还有什么方法可以访问C和m中的其他内容?我可以在创建匿名模块后为其命名吗(就像我输入“module...”一样)?如何在使用完匿名模块后将其删除,使其定义的常量不再存在? 最佳答案 三个答案:是的,使用ObjectSpace.此代码使c引用你的类(class)C不引用m:c=nilObjectSpace.each_object{|obj|c=objif(Class===objandobj.name=~/::C$/)}当然这取决于

  3. ruby-on-rails - Ruby net/ldap 模块中的内存泄漏 - 2

    作为我的Rails应用程序的一部分,我编写了一个小导入程序,它从我们的LDAP系统中吸取数据并将其塞入一个用户表中。不幸的是,与LDAP相关的代码在遍历我们的32K用户时泄漏了大量内存,我一直无法弄清楚如何解决这个问题。这个问题似乎在某种程度上与LDAP库有关,因为当我删除对LDAP内容的调用时,内存使用情况会很好地稳定下来。此外,不断增加的对象是Net::BER::BerIdentifiedString和Net::BER::BerIdentifiedArray,它们都是LDAP库的一部分。当我运行导入时,内存使用量最终达到超过1GB的峰值。如果问题存在,我需要找到一些方法来更正我的代

  4. ruby - 在 Ruby 中实现 `call_user_func_array` - 2

    我怎样才能完成http://php.net/manual/en/function.call-user-func-array.php在ruby中?所以我可以这样做:classAppdeffoo(a,b)putsa+benddefbarargs=[1,2]App.send(:foo,args)#doesn'tworkApp.send(:foo,args[0],args[1])#doeswork,butdoesnotscaleendend 最佳答案 尝试分解数组App.send(:foo,*args)

  5. ruby-openid:执行发现时未设置@socket - 2

    我在使用omniauth/openid时遇到了一些麻烦。在尝试进行身份验证时,我在日志中发现了这一点:OpenID::FetchingError:Errorfetchinghttps://www.google.com/accounts/o8/.well-known/host-meta?hd=profiles.google.com%2Fmy_username:undefinedmethod`io'fornil:NilClass重要的是undefinedmethodio'fornil:NilClass来自openid/fetchers.rb,在下面的代码片段中:moduleNetclass

  6. ruby - 使用 Vim Rails,您可以创建一个新的迁移文件并一次性打开它吗? - 2

    使用带有Rails插件的vim,您可以创建一个迁移文件,然后一次性打开该文件吗?textmate也可以这样吗? 最佳答案 你可以使用rails.vim然后做类似的事情::Rgeneratemigratonadd_foo_to_bar插件将打开迁移生成的文件,这正是您想要的。我不能代表textmate。 关于ruby-使用VimRails,您可以创建一个新的迁移文件并一次性打开它吗?,我们在StackOverflow上找到一个类似的问题: https://sta

  7. ruby-on-rails - Rails - 一个 View 中的多个模型 - 2

    我需要从一个View访问多个模型。以前,我的links_controller仅用于提供以不同方式排序的链接资源。现在我想包括一个部分(我假设)显示按分数排序的顶级用户(@users=User.all.sort_by(&:score))我知道我可以将此代码插入每个链接操作并从View访问它,但这似乎不是“ruby方式”,我将需要在不久的将来访问更多模型。这可能会变得很脏,是否有针对这种情况的任何技术?注意事项:我认为我的应用程序正朝着单一格式和动态页面内容的方向发展,本质上是一个典型的网络应用程序。我知道before_filter但考虑到我希望应用程序进入的方向,这似乎很麻烦。最终从任何

  8. ruby-on-rails - 渲染另一个 Controller 的 View - 2

    我想要做的是有2个不同的Controller,client和test_client。客户端Controller已经构建,我想创建一个test_clientController,我可以使用它来玩弄客户端的UI并根据需要进行调整。我主要是想绕过我在客户端中内置的验证及其对加载数据的管理Controller的依赖。所以我希望test_clientController加载示例数据集,然后呈现客户端Controller的索引View,以便我可以调整客户端UI。就是这样。我在test_clients索引方法中试过这个:classTestClientdefindexrender:template=>

  9. ruby-on-rails - 在混合/模块中覆盖模型的属性访问器 - 2

    我有一个包含模块的模型。我想在模块中覆盖模型的访问器方法。例如:classBlah这显然行不通。有什么想法可以实现吗? 最佳答案 您的代码看起来是正确的。我们正在毫无困难地使用这个确切的模式。如果我没记错的话,Rails使用#method_missing作为属性setter,因此您的模块将优先,阻止ActiveRecord的setter。如果您正在使用ActiveSupport::Concern(参见thisblogpost),那么您的实例方法需要进入一个特殊的模块:classBlah

  10. ruby-on-rails - 如何使用 instance_variable_set 正确设置实例变量? - 2

    我正在查看instance_variable_set的文档并看到给出的示例代码是这样做的:obj.instance_variable_set(:@instnc_var,"valuefortheinstancevariable")然后允许您在类的任何实例方法中以@instnc_var的形式访问该变量。我想知道为什么在@instnc_var之前需要一个冒号:。冒号有什么作用? 最佳答案 我的第一直觉是告诉你不要使用instance_variable_set除非你真的知道你用它做什么。它本质上是一种元编程工具或绕过实例变量可见性的黑客攻击

随机推荐