Vue Stubborn Bronze — Начало работы и компонентная коммуникация G

Vue.js
Vue Stubborn Bronze — Начало работы и компонентная коммуникация G

начиная

Поскольку это самый простой фреймворк для начала работы с интерфейсом, о начале работы с Vue говорить особо нечего.Я помещаю фрагмент кода в список.Если все могут его понять, это означает, что вы можете начать работу.

todos

<template>
  <div id="app">
    <h1>{{title}}</h1>
    <div>
      <input type="text" v-model="val">
      <button @click="add">添加</button>
      <button @click="clear">清空</button>
    </div>
    <ul>
      <li v-for="todo in todos" :key="todo.title" :class="{done:todo.done}">
        <input type="checkbox" v-model="todo.done">
        {{todo.title}}
      </li>
    </ul>
    <p>{{active}} / {{all}}</p>
  </div>
</template>

<script>
export default {
  name: "app",
  data() {
    return {
      title: "蜗牛老湿很骚气",
      val: "",
      todos: []
    };
  },
  mounted() {
    const todos = localStorage.getItem("todos");
    if (todos) {
      this.todos = JSON.parse(todos);
    } else {
      this.todos = [
        { title: "吃饭", done: true },
        { title: "睡觉", done: false },
        { title: "写代码", done: false }
      ];
    }
  },
  computed: {
    active() {
      return this.todos.filter(v => !v.done).length;
    },
    all() {
      return this.todos.length;
    }
  },
  watch: {
    todos: {
      deep: true,
      handler(todos) {
        localStorage.setItem("todos", JSON.stringify(todos));
      }
    }
  },
  methods: {
    clear() {
      this.todos = this.todos.filter(v => !v.done);
    },
    add() {
      if (this.val) {
        this.todos.push({ title: this.val, done: false });
        this.val = "";
      }
    }
  }
};
</script>
<style>
li.done {
  color: red;
  text-decoration: line-through;
}
</style>

Содержание примерно следующее.После того, как вы ознакомитесь с этим примером, это наш основной текст.Если вам что-то непонятно в приведенном выше коде, перейдите на официальный сайт Vuejs, чтобы просмотреть его.

  1. Рендеринг переменных
  2. рендеринг цикла
  3. рендеринг класса
  4. вычисляемое свойство
  5. слушатель
  6. привязать событие
  7. Жизненный цикл

составной

Однофайловый компонент Vue. Я думаю, что каждый сталкивался с однофайловым компонентом Vue.Проекты, инициализированные через vue-cli, поддерживаются автоматически.Создайте новый Child1.vue

<template>
    <div>Child1</div>
</template>
<script>
export default {
    
}
</script>


Использовать в приложении

<template>
  <div id="app">
    <Child1></Child1>
  </div>
</template>

<script>
import Child1 from '@/components/Child1'
export default {
  name: "app",
  components:{Child1}

}

</script>

Здесь возникает первый распространенный вопрос. Если компонентов слишком много, как они общаются и общаются друг с другом? Не стоит недооценивать этот вопрос. Разгневанные интервьюеры, такие как я, часто любят спрашивать. Давайте продемонстрируем Vue. Обычно используемое общение приемники между компонентами

1. Компоненты «родитель-потомок»

Самый простой способ передачи значений между родительским и дочерним компонентами — через пропсы, не будем говорить о коде.

// App
<template>
  <div id="app">
    <Child1 :title="title1"></Child1>
  </div>
</template>

<script>
import Child1 from '@/components/Child1'
export default {
  name: "app",
  data(){
    return {
      title1:'我是你爸爸'
    }
  },
  components:{Child1}

}
</script>
// Child1
<template>
    <div>
        <h2>Child2</h2>
        <div>{{title}}</div>
    </div>
</template>
<script>
export default {
    props:['title']
    
}
</script>


2. Сын к отцу

Vue предпочитает односторонний поток данных, поэтому дочерний компонент должен уведомить родительский компонент об изменении передаваемых данных и использовать $emit для запуска события, переданного родительским элементом.

<template>
  <div id="app">
    <h2>Parent</h2>
    <h3>{{msg}}</h3>
    <Child1 :title="title1" @getmsg="getmsg"></Child1>
  </div>
</template>

<script>
import Child1 from '@/components/Child1'
export default {
  name: "app",
  data(){
    return {
      msg:'',
      title1:'我是你爸爸'
    }
  },
  methods:{
    getmsg(msg){
      console.log(msg)
      this.msg = msg
    }
  },
  components:{Child1}

}

</script>
<style>

div{
  border:1px red solid;
  padding:20px;
}
</style>
// child1
<template>
    <div>
        <h2>Child2</h2>
        <p>{{title}}</p>
        <button @click="toParent">传递到父元素</button>
    </div>
</template>
<script>
export default {
    props:['title'],
    methods:{
        toParent(){
            this.$emit('getmsg','爸爸,我知道错了')
        }
    }
    
}
</script>

image-20190315144914257

3. Компоненты Brother

Компоненты Brother не могут взаимодействовать напрямую, только родительский элемент должен построить мост, и вы можете испытать это на себе.

4. Предки и потомки обеспечивают и внедряют

Пропс передается слой за слоем, а для внука дедушка нормально.Если так написать после пяти-шести слоев вложенности, то почувствуешь себя скульптурой из песка, так что вот немного непопулярный API.provice/inject, похожий на контекст в React, предназначенный для предоставления данных между слоями.

Теперь многие библиотеки с открытым исходным кодом используют этот API для обмена данными между уровнями, например, element-ui.tabsа такжеselect



<script>
import Child1 from '@/components/Child1'
export default {
  name: "app",
  provide:{
    woniu:'我是蜗牛'
  },
  components:{Child1}

}

</script>
<style>
// 子孙元素
<template>
    
    <div>
        <h3>Grandson1</h3>
        <p>
            祖先元素提供的数据 : {{woniu}}
        </p>
    </div>
</template>
<script>
export default {
    
    inject:['woniu']
}
</script>

image-20190315145836185

Однако провайдер и инжект не реагируют. Если элемент-потомок хочет уведомить предка, его нужно взломать. В Vue1 есть два метода диспетчеризации и бордкаста, но в vue2 они исключены. Мы можем смоделировать это сами.

Принцип в том, что вы можете пройти это.parent和this.детей, чтобы получить родительский компонент и дочерний компонент, мы можем немного рекурсивно

5. dispatch

Относительно просто рекурсивно получить $parent

<button @click="dispatch('dispatch','哈喽 我是GrandGrandChild1')">dispatch</button>
  methods: {

    dispatch(eventName, data) {
      let parent = this.$parent
      // 查找父元素
      while (parent ) {
        if (parent) {
          // 父元素用$emit触发
          parent.$emit(eventName,data)
          // 递归查找父元素
          parent = parent.$parent
        }else{
          break

        }
      }
 
    }
  }

dispatch

Обратите внимание, что он передается только вверх и не влияет на другие элементы.

6. boardcast

Аналогично диспетчеру, рекурсивно заставьте $children транслировать всем дочерним элементам.

<button @click="$boardcast('boardcast','我是Child1')">广播子元素</button>
function boardcast(eventName, data){
  this.$children.forEach(child => {
    // 子元素触发$emit
    child.$emit(eventName, data)
    if(child.$children.length){
      // 递归调用,通过call修改this指向 child
      boardcast.call(child, eventName, data)
    }
  });
}
{
  methods: {

    $boardcast(eventName, data) {
      boardcast.call(this,eventName,data)
    }
  }
}

boardcast

7. Смонтируйте рассылку и транслируйте по всему миру

Когда вы хотите использовать его, это слишком раздражает, чтобы нуждаться в вашей собственной компонентной внутренней отправке теорем и доске объявлений.Мы монтируем его в цепочку прототипов Vue, не очень ли это высоко, найдите main.js

Vue.prototype.$dispatch =  function(eventName, data) {
  let parent = this.$parent
  // 查找父元素
  while (parent ) {
    if (parent) {
      // 父元素用$emit触发
      parent.$emit(eventName,data)
      // 递归查找父元素
      parent = parent.$parent
    }else{
      break
    }
  }
}

Vue.prototype.$boardcast = function(eventName, data){
  boardcast.call(this,eventName,data)
}
function boardcast(eventName, data){
  this.$children.forEach(child => {
    // 子元素触发$emit
    child.$emit(eventName, data)
    if(child.$children.length){
      // 递归调用,通过call修改this指向 child
      boardcast.call(child, eventName, data)
    }
  });
}

Таким образом, его можно использовать непосредственно в компоненте без давления.

8. Несвязанный компонент: шина событий

Если два компонента не при чем, мы можем только использовать режим публикации подписки, чтобы сделать это, и смонтировать его на Vue.protytype, давайте попробуем, мы называем этот механизм механизмом шины, который является любимым event-bus


class Bus{
  constructor(){
    // {
    //   eventName1:[fn1,fn2],
    //   eventName2:[fn3,fn4],
    // }
    this.callbacks = {}
  }
  $on(name,fn){
    this.callbacks[name] = this.callbacks[name] || []
    this.callbacks[name].push(fn)
  }
  $emit(name,args){
    if(this.callbacks[name]){
      // 存在 遍历所有callback
      this.callbacks[name].forEach(cb=> cb(args))
    }
  }
}

Vue.prototype.$bus = new Bus()

использовать

// 使用
eventBus(){
    this.$bus.$emit('event-bus','测试eventBus')
}

// 监听
this.$bus.$on("event-bus",msg=>{
    this.msg = '接收event-bus消息:'+ msg
})

eventbus

По сути, Vue сам по себе является реализацией публикации подписки, давайте поленимся, мы можем удалить класс Bus и создать пустой экземпляр Vue.


Vue.prototype.$bus = new Vue()

9. vuex

Обобщив так много, на самом деле лучшая практика — это vuex, и я напишу статью, чтобы узнать об этом позже.

После прочтения этой статьи компонентная коммуникация Vue должна быть для вас сложной, и поздравляю с прохождением бронзы и официальным выходом на серебряный уровень ордена Vue.