Vue2: опора не становится связанной - PullRequest
0 голосов
/ 08 июня 2018

Примечание: я новичок в Vue, но до публикации я ознакомился с документами и искал другие вопросы.Я не мог найти ответ.У меня также есть инструмент Vue dev, установленный для отладки, и я не смог решить эту, казалось бы, простую проблему.

Я хотел создать простой однофайловый компонент Vue для тестирования и проверки работоспособности моей установки связывания с накопительным пакетом.(например, чтобы убедиться, что мое понимание компонента vue как модулей и экспорта было правильным).

Таким образом, мой простой компонент состоит из двух меньших компонентов - либо кнопки с шевроном вверх, либо шевроном вниз.Идея состояла в том, чтобы разместить это место в середине страницы и по щелчку перейти к следующему тегу section.

До сих пор я понял, что функция работает довольно хорошо (см. demo ).

Однако я хотел передать свойство двум дочерним компонентам - offsetSelector.Независимо от того, как я пытаюсь установить свойство, я не могу установить его даже на родительском уровне (например, v-bind:offsetSelector=".navbar", :offsetSelector=".navbar", offsetSelector=".navbar" и т. Д.).

Может кто-нибудь помочь мне, пожалуйставыяснить, почему это не становится ограниченным?

arrow-to-section.vue

<template>
  <div>
    <up :offsetSelector="offsetSelector"></up>
    <down :offsetSelector="offsetSelector"></down>
  </div>
</template>

<script>
import down from './section-down.vue';
import up from './section-up.vue';

export default {
  components: { down, up },
  props: [ 'offsetSelector' ],
  data: function () {
    return { }
  }
}
</script>

<style scoped>
div {
  position: fixed;
  top:50%;
  margin-left: 10px;
}

div > button {
  display: block;
  margin-bottom: 10px !important;
}
</style>

section-down.vue

<template>
  <button type="button" name="button" v-on:click="animateScrollTo">
    <i class="fa fa-chevron-down"></i>
  </button>
</template>

<script>


export default {
  props: [ 'offsetSelector' ],
  data: function () {
    return {
      offset: 0
    }
  },
  computed: {

  },
  methods: {
    setOffset: function() {
      this.offset = this.offsetSelector == undefined
      ? 0
      : $(this.offsetSelector).outerHeight() == undefined
        ? 0
        : $(this.offsetSelector).outerHeight()
    },

    animateScrollTo: function() {

      this.setOffset()


      var sections = document.querySelectorAll("section")
      var current = undefined;
      var curOffset = this.offset

      console.log('vue-down-offset', curOffset, this.offsetSelector)

      sections.forEach(function(s, i){
        var winScroll = $(window).scrollTop() - curOffset
        var curScroll = $(s).offset().top

        if ( winScroll < curScroll && current == undefined)
        { current = s }
      })

      if (current != undefined) {
        $('html, body').animate({
            scrollTop: $(current).offset().top - curOffset
        }, 1000, function() {});
      }
    }

  }
}
</script>

<style scoped>
button {
  background: radial-gradient(rgb(0, 198, 255), rgb(0, 114, 255));
  background-color: transparent;
  border: transparent 0px solid;

  margin: 0;
  padding: 0px;

  width:32px;
  height:32px;

  border-radius: 50%;
}

i { font-size: 16px; }

button:focus {
  outline: transparent 0px solid;
}
</style>

section-up.vue

<template>
  <button type="button" name="button" v-on:click="animateScrollTo">
    <i class="fa fa-chevron-up"></i>
  </button>
</template>

<script>


export default {
  props: [ 'offsetSelector' ],
  data: function () {
    return { offset: 0 }
  },
  computed: { },
  methods: {
    setOffset: function() {
      this.offset = this.offsetSelector == undefined
      ? 0
      : $(this.offsetSelector).outerHeight() == undefined
        ? 0
        : $(this.offsetSelector).outerHeight()
    },

    animateScrollTo: function() {
      this.setOffset()

      var sections = document.querySelectorAll("section")
      var current = undefined;
      var curOffset = this.offset
      console.log('vue-up-offset', curOffset, this.offsetSelector)

      sections.forEach(function(s, i){
        var winScroll = $(window).scrollTop()
        var curScroll = $(s).offset().top - curOffset

        if ( winScroll > curScroll)
        { current = s }
      })
      if (current == undefined) {
        current = document.querySelector("body")
      }

      if (current != undefined) {
        $('html, body').animate({
            scrollTop: $(current).offset().top - curOffset
        }, 1000, function() {});
      }
    }

  }
}
</script>

<style scoped>
button {
  background: radial-gradient(rgb(0, 198, 255), rgb(0, 114, 255));
  background-color: transparent;
  border: transparent 0px solid;

  margin: 0;
  padding: 0px;

  width:32px;
  height:32px;

  border-radius: 50%;
}


button:focus {
  outline: transparent 0px solid;
}

i { font-size: 16px; }
</style>

demo.html

<style media="screen">
    section {
      height: 100vh;
    }
  </style>


  <body>
    <nav class="navbar navbar-light sticky-top">
      <a class="navbar-brand" href="../../">
          <img src="../../data/vdsm.svg" alt="logo" style="width:150px;">
          <h4 class="lead"> vue components </h4>
      </a>
      <crumbs id="crumbs"></crumbs>
    </nav>
    <arrowToSection id="arrowToSection" offset-selector=".navbar"></arrowToSection>

    <section style="background-color:#5433FF;"></section>
    <section style="background-color:#20BDFF;"></section>
    <section style="background-color:#A5FECB;"></section>
    <section style="background-color:#86fde8;"></section>

  </body>

  <script type="text/javascript" src="component.js"></script>

component.js

let arrowToSection = vdsm.arrowToSection
new Vue({
  el: '#arrowToSection',
  template: '<arrowToSection/>',
  components: { arrowToSection }
})

База кода

Репо можно найти здесь .

Два дочерних компонента:

  • / src / scripts / modules / section-up.vue
  • / src / scripts /modules / section-down.vue

Компонент, над которым я работаю:

  • / src / scripts / modules / arrow-to-section.vue

Демонстрация компонента:

  • / demos / arrow-to-section / index.html

Ответы [ 2 ]

0 голосов
/ 08 июня 2018

Почему это не работает

На самом деле, ответ довольно тривиален: вы не ставите какие-либо реквизиты на свой arrowToSection компонент.В то время как в вашем теле есть элемент с озадачивающим названием <arrowToSection>, компонент arrowToSection не смонтирован на нем - по крайней мере, не напрямую.Вы создаете компонент arrowToSection внутри анонимного экземпляра Vue, созданного в component.js, здесь: template: '<arrowToSection/>'.И вы не передаете ему никаких реквизитов.

Как это исправить

Чтобы это исправить, вам нужно пропустить опору здесь:

let arrowToSection = vdsm.arrowToSection
new Vue({
  el: '#arrowToSection',
  template: '<arrowToSection :offsetSelector="'.navbar'" />',
  components: { arrowToSection }
})

Далее вы можете спроситьmsgstr "почему бы не добавить опору к этому анонимному элементу, а вместо этого использовать значение, установленное в теле HTML".Ответ на этот вопрос - это способ передачи значений между компонентами Vue .Внешний HTML не является компонентом Vue, и вы не можете передавать реквизиты оттуда.Атрибуты, которые вы помещаете в элемент #arrowToSection, являются просто обычными атрибутами (и весь элемент заменяется, и аргументы теряются, кстати).

Позже примечание: Этот пример в документации показываетатрибуты, по-видимому, читаются из элемента HTML.Это кажется несколько противоречивым с моим экспериментом.Возможно, что проходящие реквизиты будут работать, если вы используете полную запись v-bind:prop="..." вместо :prop="...".

Альтернативные решения с propsData

Если вы действительно хотите использовать реквизиты, вы можете использовать propsData :

let arrowToSection = vdsm.arrowToSection
new Vue({
  el: '#arrowToSection',
  props: ['offsetSelector'],
  propsData: {
    offsetSelector: '.navbar',
  },
  template: '<arrowToSection :offsetSelector="offsetSelector" />',
  components: { arrowToSection }
})

Как видите, это действительно надумано и не имеет смысла.Однако вам не нужен промежуточный компонент, поэтому, по крайней мере, на практике вы можете использовать propsData следующим образом:

let arrowToSection = vdsm.arrowToSection
new Vue(Object.assign({}, arrowToSection, {
  el: '#arrowToSection',
  propsData: {
    offsetSelector: '.navbar',
  },
}))

Отказ от ответственности: я не уверен, что использование компонентов этопуть официально поддерживается.Возможно нет.Но это работает.

0 голосов
/ 08 июня 2018

Я не полностью прочитал ваш репозиторий, но, насколько я вижу, ответ можно найти здесь: https://vuejs.org/v2/guide/components-props.html

Имена атрибутов HTML не чувствительны к регистру, поэтому браузеры будут интерпретировать любыепрописные буквы как строчные.Это означает, что при использовании встроенных в DOM шаблонов имена верблюдов camelCased должны использовать их эквиваленты в кебабах (с разделителями-дефисами):

В основном проп в списке проппсов имеет значение camelCase, но внутри атрибута html это kebap-case.Я надеюсь, что это помогает:)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...