官方文档

https://shiny.rstudio.com/articles/understanding-reactivity.html

理解

14977949-b49d6e81c7c9dcf4.png

1. reactive 和 eventReactive

reactive 是模块化反应机制,如下代码中fib(as.numeric(input$n))被单独执行了两次,浪费资源。

  1. fib <- function(n) ifelse(n<3, 1, fib(n-1)+fib(n-2))
  2. server <- function(input, output) {
  3. output$nthValue <- renderText({ fib(as.numeric(input$n)) })
  4. output$nthValueInv <- renderText({ 1 / fib(as.numeric(input$n)) })
  5. }

我们使用reactive可以生成一个中间表达式,暂存结果在currentFib,后面调用currentFib省去计算过程。

  1. fib <- function(n) ifelse(n<3, 1, fib(n-1)+fib(n-2))
  2. server <- function(input, output) {
  3. currentFib <- reactive({ fib(as.numeric(input$n)) })
  4. output$nthValue <- renderText({ currentFib() })
  5. output$nthValueInv <- renderText({ 1 / currentFib() })
  6. }

reactive会时刻监视 input 的每一个改变做出响应,但是有时候我们并不希望如此。例如运用多个条件对数据进行筛选的时候,我们可能是一个一个条件输入的,并不希望每改变一个条件就输出一个表格或者图片,这样会很浪费计算资源。这个时候希望更改完所有条件后,一起提交输入,进行计算,需要用到eventReactive

  1. ## 这个例子在拖动控件的时候,输出的表格会随着变化
  2. library("shiny")
  3. shinyApp(
  4. ui = fluidPage(
  5. column(4,
  6. sliderInput("x", "Value",
  7. min = 1, max = 10,
  8. value = 3),
  9. actionButton("button", "Show")
  10. ),
  11. column(8, tableOutput("table"))
  12. ),
  13. server = function(input, output) {
  14. df <-reactive({
  15. head(cars, input$x)
  16. })
  17. output$table <- renderTable({
  18. df()
  19. })
  20. }
  21. )
  1. ## 这个滑动控件后,只有监视到按钮事件,输出才发生改变
  2. shinyApp(
  3. ui = fluidPage(
  4. column(4,
  5. sliderInput("x", "Value",
  6. min = 1, max = 10,
  7. value = 3),
  8. br(),
  9. actionButton("button", "Show")
  10. ),
  11. column(8, tableOutput("table"))
  12. ),
  13. server = function(input, output) {
  14. df <- eventReactive(input$button, {
  15. head(cars, input$x)
  16. })
  17. output$table <- renderTable({
  18. df()
  19. })
  20. }
  21. )

2. observe 和 observeEvent

observereactive 相同点都是能响应 input 的变化,不同点是 observer 没有返回值,不能向下传递,所以就不能作为 render 的输入。顾名思义,它只是起监视作用。下面例子,当滑动使 x > 5时,界面发送通知。

  1. shinyApp(
  2. ui = fluidPage(
  3. sliderInput("x", "Value",
  4. min = 1, max = 10,
  5. value = 3)
  6. ),
  7. server = function(input, output) {
  8. observe({
  9. if(input$x > 5)
  10. showNotification("value > 5")
  11. })
  12. }
  13. )

14977949-67042157a08d3f2b.png
相同的 observeEvent 只是再增加一个监视条件,起延时作用。例如下面例子,滑动滑杆时,并不去判断 x > 5,只有按下按钮,才执行下面的代码。

  1. shinyApp(
  2. ui = fluidPage(
  3. sliderInput("x", "Value",
  4. min = 1, max = 10,
  5. value = 3),
  6. actionButton("go", "Go")
  7. ),
  8. server = function(input, output) {
  9. observeEvent(input$go,{
  10. if(input$x > 5)
  11. showNotification("value > 5")
  12. })
  13. }
  14. )

14977949-dadfc1dfd8e40198.png