【问题标题】:vue2 reactive filter values?vue2 反应式过滤器值?
【发布时间】:2017-02-20 20:27:56
【问题描述】:

当 vm 数据更新时,我无法更新计算的过滤器值。就我而言,我在 UTC 的 VM 模型上存储了一些时刻日期时间。然后我有一个过滤器,它显示那些使用时刻格式化为时区的时间。然后,如果用户需要,我想要切换时区,但是当他们切换时区时,过滤器值不会相应更新。我是否错过了一些让他们反应的东西?此外,它甚至没有使用我的默认值selectedTz: 'America\Los_Angeles'(您会注意到,尽管有此默认设置,但它开始时始终显示为 TZ +0 (UTC))。

var app = new Vue({
        el: '#app',
        data: {
            games: [{start_time: '2017-01-23 21:00:00'}, {start_time: '2017-01-23 22:00:00'}, {start_time: '2017-01-23 23:00:00'}],
            selectedTz: 'America/Los_Angeles'
        },
        methods: {
            switchToEast: function () {
                this.selectedTz = 'America/New_York'
            },
            switchToWest: function () {
                this.selectedTz = 'America/Los_Angeles'
            }
        },
        filters: {
            usertz: function (date) {
                var tz = this.selectedTz
                var x = new moment.tz(date, 'Etc/UTC')
                x.tz(tz)
                return x.format('MMM Do @ h:mm a Z')
            }
        }
    })
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.17.1/moment.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment-timezone/0.5.11/moment-timezone-with-data.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.1.10/vue.min.js"></script>
<div id="app">
    <p class="text-right">All times are in {{ selectedTz }}</p>
    <div class="text-right">
        <button class="button" @click="switchToEast()">East</button>
        <button class="button" @click="switchToWest()">West</button>
    </div>
    <p v-for="game in games">
        {{ game.start_time | usertz }}
    </p>
</div>

【问题讨论】:

    标签: javascript datetime momentjs vuejs2


    【解决方案1】:

    我也遇到过这样的过滤器问题。无法使用过滤器解决它,并决定使用计算属性来解决。在我看来,过滤器不能处理太多的计算。文档本身说

    过滤器主要用于文本转换目的

    像我这样尝试它,它应该可以工作。

    var app = new Vue({
            el: '#app',
            data: {
                games: [{start_time: '2017-01-23 21:00:00'}, {start_time: '2017-01-23 22:00:00'}, {start_time: '2017-01-23 23:00:00'}],
                selectedTz: 'America/Los_Angeles'
            },
            methods: {
                switchToEast: function () {
                    Vue.set(this, 'selectedTz', 'America/New_York')
                },
                switchToWest: function () {
                    Vue.set(this, 'selectedTz', 'America/Los_Angeles')
                }
            },
            computed: {
                filteredGames: function () {
                    var filteredList = []
                    for (i = 0; i < this.games.length; i++) { 
                        var x = new moment.tz(this.games[i].start_time, 'Etc/UTC')
                        x.tz(this.selectedTz)
                        filteredList.push({start_time: x.format('MMM Do @ h:mm a Z')})
                    }
                    return filteredList
                }
            }
        })
    <script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.17.1/moment.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/moment-timezone/0.5.11/moment-timezone-with-data.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.1.10/vue.min.js"></script>
    <div id="app">
        <p class="text-right">All times are in {{ selectedTz }}</p>
        <div class="text-right">
            <button class="button" @click="switchToEast()">East</button>
            <button class="button" @click="switchToWest()">West</button>
        </div>
        <p v-for="game in filteredGames">
            {{ game.start_time }}
        </p>
    </div>

    【讨论】:

    • 我考虑过这种方法,但它似乎“不那么优雅”,但我想如果过滤器不能那样工作,我将不得不这样做。谢谢!
    • 我同意你的看法。在我看来,能够在这里使用过滤器也会更酷。尽管如此,我认为它不会起作用。如果您在 tz 上的过滤器中执行 console.log,您会看到它是未定义的。很遗憾,因为我想用过滤器做更多事情。
    • 过滤器更优雅,您可以使用它...但它唯一相关的就是格式...不要更改时区,这更适合作为计算属性...
    【解决方案2】:

    虽然被标记为正确的答案运行......它委托给计算机属性来转换日期和格式以进行演示。而格式应该是过滤器的工作。

    更改对所选属性做出反应的时区,实际上是计算属性的工作。但是您可以让计算属性将所有日期转换为 Moment.js 对象,并仅使用过滤器来格式化日期的呈现……这正是过滤器的工作。

    var app = new Vue({
        el: '#app',
        data: {
            games: [{start_time: '2017-01-23 21:00:00'}, {start_time: '2017-01-23 22:00:00'}, {start_time: '2017-01-23 23:00:00'}],
            selectedTz: 'America/Los_Angeles'
        },
        methods: {
            switchToEast: function () {
                Vue.set(this, 'selectedTz', 'America/New_York')
            },
            switchToWest: function () {
                Vue.set(this, 'selectedTz', 'America/Los_Angeles')
            }
        },
        computed: {
            filteredGames: function () {
                var filteredList = []
                for (var game of this.games) {
                    var start_time = new moment.tz(game.start_time, 'Etc/UTC')
                    start_time.tz(this.selectedTz)
    
                    game.start_time = start_time
                    filteredList.push(game)
                }
    
                return filteredList
            }
        },
        filters: {
            datetime: function(date) {
                return date.format('MMM Do @ h:mm a Z')
            }
        }
    })
    <script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.17.1/moment.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/moment-timezone/0.5.11/moment-timezone-with-data.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.1.10/vue.min.js"></script>
    <div id="app">
        <p class="text-right">All times are in {{ selectedTz }}</p>
        <div class="text-right">
            <button class="button" @click="switchToEast()">East</button>
            <button class="button" @click="switchToWest()">West</button>
        </div>
        <p v-for="game in filteredGames">
            {{ game.start_time | datetime }}
        </p>
    </div>

    【讨论】:

    • 这也是一个很好的解决方案,昨天仔细考虑之后我完全同意你的说法
    【解决方案3】:

    过滤器可以采用额外的参数。如果将所有反应变量从函数体移动到参数,它应该可以工作。例如:

    <template>
      {{ message | filter(data) }}
    </template>
    
    <script>
      export default {
        filters: {
          filter(message, data) {
            return `Message: ${message}, Data: ${data}`;
          },
        },
    
        data() {
          return {
            data: "Try changing me!",
          };
        },
    
        props: {
          message: String,
        },
      };
    </script>
    

    或者在你的例子中:

    var app = new Vue({
            el: '#app',
            data: {
                games: [{start_time: '2017-01-23 21:00:00'}, {start_time: '2017-01-23 22:00:00'}, {start_time: '2017-01-23 23:00:00'}],
                selectedTz: 'America/Los_Angeles'
            },
            methods: {
                switchToEast: function () {
                    this.selectedTz = 'America/New_York'
                },
                switchToWest: function () {
                    this.selectedTz = 'America/Los_Angeles'
                }
            },
            filters: {
                usertz: function (date, tz) {
                    var x = new moment.tz(date, 'Etc/UTC')
                    x.tz(tz)
                    return x.format('MMM Do @ h:mm a Z')
                }
            }
        })
    <script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.17.1/moment.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/moment-timezone/0.5.11/moment-timezone-with-data.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.1.10/vue.min.js"></script>
    <div id="app">
        <p class="text-right">All times are in {{ selectedTz }}</p>
        <div class="text-right">
            <button class="button" @click="switchToEast()">East</button>
            <button class="button" @click="switchToWest()">West</button>
        </div>
        <p v-for="game in games">
            {{ game.start_time | usertz(selectedTz) }}
        </p>
    </div>

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-10-11
      • 1970-01-01
      • 2023-01-14
      • 2021-05-29
      • 2023-03-20
      • 2019-03-14
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多