函数式编程和DOM操作 [英] Functional programming and DOM manipulation

查看:42
本文介绍了函数式编程和DOM操作的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

以功能"方式编写的脚本中操作DOM的最纯"方式是什么.

How is most "pure" way to manipulate DOM in script written in "functional" way.

例如,如果我只需要更改元素宽度,我应该使用典型的语法,例如:

For example if I simply need to change element width should I use typical syntax like:

document.querySelector(".class").style.width = ...

或编写专用功能,例如:

or write dedicated function, like:

function resize(el, w) {
    return el.style.width = w;
}

resize(document.querySelector(".class", 100));

我认为,我了解函数式编程的一般概念,但是我遇到的所有示例都集中在处理数字或字符串上.操作DOM被认为是副作用,因此我想知道如何以正确的方式进行操作.

I think, I understand general idea of functional programming but all examples I encountered are focused on manipulating numbers or strings. Manipulating DOM is considered side-effect so I'm wondering how to do it in correct way.

下面更新的代码,问题是,它是否功能正常?如果不是这样,我将不胜感激,建议如何重写它.

Updated code below, the question is, is iit functionall? If not I'd be gratefull for suggestion how to rewrite it.

"use strict";

const outerW = num => 100 * num + "%";
const innerW = num => 100 / num + "%";
const setW = (el, w) => el.style.width = w;

const mask = document.querySelector(".slider__slides__mask");
const slides = document.querySelectorAll(".slider__slide");

setW(mask, outerW(slides.length));
slides.forEach(function(item) {
    setW(item, innerW(slides.length));
});

推荐答案

每个有意义的程序最终都必须发挥某些作用,无论是功能式还是命令式的.函数式编程的思想是将这些效果转移到程序的边缘,以便使大部分内容保持纯净.这样可以更轻松地进行推理.

Every meaningful program must eventually carry out some effects, whether it is in functional or imperative style. The idea of functional programming is to shift theses effects to the edge of a program, so that a large portion remains pure. This makes it much easier to reason about it.

但是如何实践呢?

Javascript函数通常定义为多参数函数.因此,我们不能在调用方推迟对它们的评估:

Javascript functions are usually defined as multi-argument functions. Hence we can't defer their evaluation at the calling side:

// pure

const add = (x, y) => x + y;

const log = x => console.log(x);

// impure

log(add(2, 3));

命令式样式相同:

let x = 2, y = 3;

// impure

console.log(x + y);

结果是纯计算(add)无法与效果(log)分开.对于这个草图来说,这并不是什么大问题,但是一旦您的程序变大,这些分散的效果就会削弱其可读性和可理解性.

The consequence is that the pure computation (add) can not be separated from the effect (log). This isn't a big deal for this sketch, but as soon as your program grows bigger, these scattered effects impair its readability and comprehensibility.

为防止这种行为,功能必须可组合,即它们的最后一个参数必须部分适用:

To prevent this behavior functions must become composable, i.e. their last argument must be partially applicable:

// pure

const comp = (f, g) => x => f(g(x));

const add = x => y => x + y;

const log = x => console.log(x);

const addAndLog = comp(log, add(2));

// impure

addAndLog(3);

您可能希望查看 currying 以获得更多信息.

You might want to look into currying for more information.

使用重击功能,我们可以将效果进一步移到边缘.一个thunk只是一个不包含任何参数的函数,因此表示延迟的计算:

Using thunks we can move the effects even further to the edges. A thunk is just a function that expects no arguments and thus represents a deferred computation:

// pure

const comp = (f, g) => x => f(g(x));

const add = x => y => x + y;

const log = x => () => console.log(x);

const addAndLog = comp(log, add(2));

const eventuallyLog = addAndLog(3); // still pure

// impure (release the effect)

eventuallyLog(); // invoke the thunk

您可能希望查看 IO monads 了解更多信息

You might want to look into IO monads for more information.

// pure

const on = (type, element) => f => {
  element.addEventListener(type, f, true);
  return () => element.removeEventListener(type, f, true);
}

const compose = (...fs) => x => fs.reduce((acc, f) => f(acc), x);

const countFrom = x => () => (x++, x);

const log = x => console.log(x);

const filter = pred => f => x => pred(x) ? f(x) : x;

const even = x => x % 2 === 0;

const concat = y => x => x + y;

const filterEven = filter(even);

const clickStream = on("click", document);

const computation =
 compose(countFrom(0), filterEven(compose(concat("!"), log)));

// impure (release the effects)

console.log("click on the section above");

clickStream(computation);

作为副作用(双关语意味)

As a side effect (pun intended)

compose(countFrom(0), filterEven(compose(concat("!"), log)))

读起来像普通的英语.最近有人告诉我,这不是理想的属性.好吧,我不同意.

reads like plain English. I was recently told that this is not a desirable property. Well, I disagree.

这篇关于函数式编程和DOM操作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆