Краткий обзор новых функций Vue3, быстрое освоение

Vue.js внешний фреймворк

Эта статья мояофициальный сайт вьюА также некоторые учебные записи и опыт изучения v3 в других местах, если есть что-то, что вы не можете понять, пожалуйста, поправьте меня.


1. Изменения в данных

В версии v3 возвращаемое значение данных стандартизировано и принимается толькоФункция, возвращающая объект, а в версии v2 также поддерживается возвратObjectа такжеФункция, возвращающая объект.

2. Изменения в слиянии миксинов

Слияние объектов в v3 — это перезапись, а не слияние.

const mixinObject = {
  data(){
    return {
      user:{
        id:1,
        name:'jack'
      }
    }
  }
}

const CompA = {
  mixins: [mixinObject],
  data() {
    return {
      user: {
        id: 2
      }
    }
  }
}

// 结果是
user: {
  id: 2
}

3. Удалены методы $on, $off, $once

В версии v2 $on и $off обычно используются для реализации глобальной шины событий, а $once используется для привязки пользовательского события. На самом деле в реальных проектах они почти не используются. После удаления версии v3, и соответствующие требования могут быть выполнены с помощью некоторых внешних библиотек. Напримерmitt

4. Убран фильтр

Фильтры были удалены в версии v3,{{ calcNum | filter }}Больше не будет поддерживаться, официальная рекомендация - использоватьcomputedФильтр замены атрибутов (молодцы ~).

5. Фрагменты

В версии v3 поддерживаются компоненты, которые могут иметь несколько корневых узлов, что может уменьшить глубину иерархии узлов. Но я также надеюсь, что разработчики смогут прояснить семантику.

<template>
  <header></header>
  <main></main>
  <footer></footer>
</template>

6. Функциональные компоненты

Прежде чем мы изменим версию v3, давайте рассмотрим версию функционального компонента v2, которую можно создать двумя способами:functionalатрибуты и{ functional : true }варианты, коды следующие

// attribute 方式
<template functional>
  <img :src="src" />
</template>
<script>
...
</script>


// 选项方式
export default = {
  functional:true,
  props:{
      ...
  },
  render:function(createElement,context){
      ...
      /**
       context传递了一些参数:
       props,slots,parent,listeners,injections
      **/
  }
}

В версии v2 есть два типа компонентов: компоненты с состоянием и функциональные компоненты (компоненты без состояния).По сравнению с компонентами с состоянием, функциональные компоненты не требуют создания экземпляров, не имеют состояния и не имеют обработчиков жизненного цикла.Рендеринг намного быстрее, чем у компонентов с отслеживанием состояния. Часто используется для статических компонентов представления с единственной функцией для оптимизации производительности. Кроме того, функциональные компонентыВозможность возврата нескольких корневых узлов.

В версии 3 разница в производительности между компонентами с отслеживанием состояния и функциональными компонентами была значительно уменьшена и в большинстве сценариев почти незначительна. Таким образом, единственным преимуществом функциональных компонентов является возможность возврата нескольких узлов, но это обычно используется меньше, и компоненты часто проще Конкретный синтаксический сахар выглядит следующим образом:

// 函数创建
import { h } from 'vue'

const DynamicHeading = (props, context) => {
  // context是一个包含 attrs,slots,emit的对象 
  return h(`h${props.level}`, context.attrs, context.slots)
}

DynamicHeading.props = ['level']

export default DynamicHeading


// 单文件组件(SFC)
<template>
  <component
    v-bind:is="`h${$props.level}`"
    v-bind="$attrs"
  />
</template>

<script>
export default {
  props: ['level']
}
</script>

7. Глобальная настройка API

В версию v3 добавлен новый глобальный API.createApp, импортированный через модуль ES. передачаcreateAppВозвращает экземпляр приложения, который предоставляет глобальный API, который представляет собой новую концепцию Vue3, которая в основном решает возможность совместного использования ресурсов (конфигурация, глобальные компоненты, директивы и т. д.) между различными «приложениями». Давайте сравним изменения в v3 и v2 для создания приложений соответственно.

// v2 创建
import Vue from 'vue'
import App from './App.vue'

Vue.config.productionTip = false

new Vue({
  render: h => h(App),
}).$mount('#app')


// v3 创建

import { createApp } from 'vue'
import App from './App.vue'

var app = createApp(App);
app.mount('#app')

Одним из способов обмена конфигурацией между «приложениями» является заводской шаблон:

import { createApp } from 'vue'
import App1 from './App1.vue'
import App2 from './App2.vue'

const createMyApp = options => {
  const app = createApp(options)
  app.directive('focus' /* ... */)
  return app
}

createMyApp(App1).mount('#foo')
createMyApp(App2).mount('#bar')

v3 перемещает API, который может глобально изменить поведение Vue, из исходного конструктора Vue в экземпляр. Список выглядит следующим образом

глобальный API v2 глобальный API v3
Vue.config app.config
Vue.config.productionTip Удалить
Vue.config.ignoredElements app.config.ignoredElement
Vue.component app.component
Vue.directive app.directive
Vue.mixin app.mixin
Vue.use app.use

Кроме того, некоторые глобальные API и внутренние компоненты подверглись рефакторингу, учитывая tree-shaking, их можно импортировать только через ES-модули, а это значит, что когда компоненты и интерфейсы, которые не используются в вашем приложении, не будут упакованы. Список затронутых API выглядит следующим образом:

  • Vue.nextTick
  • Vue.observable (заменен на Vue.reactive)
  • Vue.version
  • Vue.compile (только полная сборка)
  • Vue.set (только совместимые сборки)
  • Vue.delete (только совместимые сборки)
// 错误使用
import Vue from 'vue'

Vue.nextTick(() => {
  // 一些和DOM有关的东西
})


// 正确使用
import { nextTick } from 'vue'

nextTick(() => {
  // 一些和DOM有关的东西
})

8. API композиции

основное событие! ! !

Это новая концепция в версии 3, vue предоставляет нам несколько новых API, эти новые API используются в одном месте, и это место принадлежит нам.новыйПредоставляет место, где мы можем сделать что-то от инициализации компонента до его уничтожения, что я понимаю как функцию ловушки -Setup, В настройках вы можете делать все, что вы можете делать в компонентах vue, например, когда выcreated,mounted,computed,watch,methodsВсе, что вы там делаете, может бытьSetupОн выполнен внутри, так как мы можем это сделать, то есть через новые API, предоставляемые Vue.

Так что же в основном решает эта штука? Все мы знаем, что роль компонентов заключается в извлечении функций и повторном использовании кода. Это заставляет нашу программу идти дальше с точки зрения гибкости и ремонтопригодности, но этого недостаточно.Когда логика внутри компонента очень сложная, мы будем выделять логику вcreated,mounted,methods,computed,watchВнутри, а затем и весь код файла состоит из сотен строк. Это, несомненно, самое хлопотное для людей, которые не писали этот компонент, пытаясь понять эти логические коды. а такжеSetupЭто то, что решает эту проблему, централизуя всю логику вSetupв процессе. Отныне, когда вы хотите построить автомобиль, вам больше не нужно ездить по всему миру, чтобы импортировать все виды деталей, вы находитесь вSetupможно сделать на заводе.

давай познакомимсяSetupи эти новыеAPIИспользование и функции (я слышал, что такие вещи называются галантерейными товарами???):

Setup

Если вы понимаете, что я сказал выше, вы должны понимать и то, что я написал в начале:

<template>
  <div class="demo">
  </div>
</template>
<script>
export default {
  name:"Demo",
  data(){
    return {}
  },
  setup () {
    console.log('run');
  }
}
</script>

// 当运行起来打印了run

SetupМожет возвращать объект, и вы можете получить доступ к свойствам этого объекта в другом месте компонента.

Примечание: при выполненииSetupКогда экземпляр компонента не был создан, поэтому вSetupНет вthis. Однако он предоставляет два параметра приема -propsа такжеcontext. существуетSetupне может получить доступ к каким-либо другим свойствам в компоненте.

// 调用Demo组件
<Demo :name="'jac" a="1" b="2"></Demo>

// Demo 组件
<template>
  <div class="demo">
  </div>
</template>
<script>
export default {
  name:"Demo",
  props:{
    name:String,
  },
  data(){
    return {}
  },
  setup (props,context) {
    console.log('props',props); // {name:jac}
    console.log('attrs', context.attrs); // {a:1,b:2}
    console.log('slots', context.slots); // {}
    console.log('emit', context.emit); // function
    
    let shareProp = 'hallo,v3';
    
    // 返回两个属性 shareProp, changeProp
    return {
      shareProp
    }
  },
  mounted() {
    this.shareProp = 'changed';
  },
}
</script>

Мы обнаружим, что пытаясь и не обновляя, мы находимsetupВозвращаемый объект не является реактивным,ОтзывчивыйМы не должны быть незнакомы, все свойства в опции data() являются адаптивными, то есть Vue должен был создать зависимость от свойств в data() во время процесса инициализации компонента. Поэтому, когда свойство изменяется, представление автоматически обновляется, что является отзывчивым. Так как же сделать его отзывчивым?

ref & reactive

мы можем пройтиref,reactiveСоздайтеОтзывчивыйусловие,

Мы используемrefВы можете создавать реактивные состояния примитивных и сложных типов данных, используяreactiveСоздавать можно только реактивные состояния сложных типов данных, если созданный тип данных неверный, консоль выдаст соответствующее предупреждениеvalue cannot be made reactive: **. Этоrefа такжеreactiveВ чем разница?

const refNum = ref(10);
const refObj = ref({
  name:'jac',
  age:20
});
const reactiveNum = reactive(10);
const reactiveObj = reactive({
  name: 'jac',
  age: 20
})
console.log('refNum',refNum);
console.log('refObj',refObj);
console.log('reactiveNum', reactiveNum);
console.log('reactiveObj', reactiveObj);

Результат выглядит следующим образом:

когдаrefКогда создается сложный тип данных, он фактически создается внутри с помощью реактивного. такrefТакже возможно создавать состояния ответа сложных типов данных, просто вsetupКитайская орфография будет другой.

setup(){
  const refObj = ref({
    name:'jac',
    age:20
  });
  const reactiveObj = reactive({
    name: 'jac',
    age: 20
  })
  // ref 方式的更新
  const changeRefObj = () => {
    refObj.value.name="mac"
  }
  // reactive 方式的更新
  const changeReactiveObj = () => {
    reactiveObj.name = 'mac'
  }
  return {
    ...
  }
}

Уведомление: пройти черезrefЗначение завернуто вSetupв вам нужно использоватьпеременная.значениеспособ доступа и установки значений изSetupВы можете напрямую передавать объекты, выставленные вэта переменнаядоступ.

<template>
  ...
</template>
<script>
import { ref,reactive } from 'vue';
export default {
  ...
  setup (props,context) {
    ...
    let shareProp = ref('hallo,v2');
    let info = reactive({name:'jac'});
    const changeProp = ()=>{
      shareProp.value = 'hallow,v3';
    }
    return {
      shareProp,
      ...
    }
  },
  mounted() {
    console.log(this.shareProp)
  },
}
</script>

Небольшие партнеры могут выбрать использование в соответствии со своими привычками кодирования.

toRef & toRefs

Иногда, когда мы хотим удалить некоторые переменные из сложной реактивной переменной путем деструктурирования, наш код может выглядеть так:

<template>
  <button @click="changeObj">my name is {{info.name}}</button>
</template>
<script>
import { ref, provide, reactive } from 'vue';
export default {
  name: 'Demo',
  setup(){
    const info = reactive({name:'jac',sex:'男',age:18});
    return {
      info
    }
  },
  methods:{
    changeObj(){
      let { name,sex } = this.info;
      name = 'make'
      // 视图不会更新
    }
  }
}
</script>

Это приведет к тому, что два свойства, которые мы деконструировали, перестанут отвечать на запросы.toRefа такжеtoRefsдеконструируется из него,toRefРеактивные переменные для деконструкции одного свойства,toRefsЭто создание адаптивных переменных для всех свойств в исходном объекте и создание соответствующих переменных путем деструктурирования.

<template>
  <button @click="changeObj">my name is {{info.name}}</button>
</template>
<script>
import { ref, provide, reactive, toRef, toRefs} from 'vue';
export default {
  name: 'Demo',
  setup(){
    const info = reactive({name:'jac',sex:'男',age:18});
    return {
      info
    }
  },
  methods:{
    changeObj(){
      // toRef
      // let name = toRef(this.info,'name'); // arg1: 源对象, arg2: 属性名称
      // name.value = 'make'
		
      // toRefs  
      // let { name } = toRefs(this.info); // arg1: 源对象
      // name.value = 'make'
      
      // 视图成功刷新
    }
  }
}
</script>

смотреть, вычислять и регистрировать хуки жизненного цикла

существуетSetupмы все еще можемwatchсвойства, создавать независимыеcomputed, вы также можете зарегистрировать различные хуки жизненного цикла, так какSetupЭтапы выполнения вращаются вокругbeforeCreateа такжеcreatedи прогресс, поэтому то, что изначально было сделано в этих двух жизненных циклах, может быть помещено вSetupв процессе.

<template>
  ...
</template>
<script>
import { ref, toRefs, watch, computed, onMounted } from 'vue';
export default {
  name:"Demo",
  props:{
    name:String,
  },
  ...
  setup (props,context) {
    console.log('我首先执行');
    // 通过toRefs方法创建props的响应式变量
    const { name: listenName } = toRefs(props);
    const count = ref(0);
    const changCount = ()=>{
      count.value++;
    }
    const totalCount = computed(() => {
      return `总计数:${count.value}`
    })
    // watch 会监听listenName变量,当listenName变量改变的时候会触发回调方法
    watch(listenName,(newValue, oldValue)=>{
      console.log(listenName.value); 
    })
    onMounted(()=>{
      console.log('onMounted也执行了,结果输出如下');
      console.log(count.value);
      changCount();
      console.log(totalCount.value)
    })
    return {
      count,
      changCount,
      totalCount,
    }
  },
  created() {
    console.log('created执行了');
  },
  mounted() {
    console.log('mounted执行了');
  },
}
</script>

// 输出结果如下:
我首先执行
created执行了
onMounted也执行了,结果输出如下
0
总计数:1
mounted执行了

могу видеть,SetupФункция ловушки жизненного цикла, зарегистрированная во внешнем регистре, выполняется раньше функции ловушки, зарегистрированной снаружи!

provide & inject

provideа такжеinjectОбычно мы не используем его много в бизнес-сценариях, но он все еще полезен при записи библиотек плагинов или компонентов.provideа такжеinjectИспользуется для предоставления свойств в компонентах-предках и внедрения их в дочерние компоненты. Как это использовать в настройках?

// demo组件中提供
<template>
  <Test />
</template>
<script>
import { provide } from 'vue';
export default {
  name:"Demo",
  setup (props,context) {
    provide('name','jac')
  },
}
</script>

// test组件中注入使用
<template>
  ...
</template>
<script>
import { inject } from 'vue';
export default {
  name:"Test",
  setup (props,context) {
    console.log(inject('name')); // jac
  },
}
</script>

ВышеsetupОсновное применение , вам нужно хорошо его прочувствовать и использовать в различных сценариях, чтобы лучше понять, в чем он хорош, например следующий код:

// a.js
import { ref, onMounted } from 'vue'
export default function doSomething(refName,fn){
  const a = ref(0);
  const b = ref(0);
  // ...,
  onMounted(() => {
   fn();
  })

  return {
    a,
    b
  }
}

//b.js
import doSomething from './a.js';
setup(){
  const {a,b} = doSomething('box',()=>{
    console.log('执行');
  })
}

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

9. v-model

В версии 3 значение атрибута по умолчанию и метод триггера v-модели были изменены.value=>modelVale,input=>update. В пользовательском компоненте он позволяет нам устанавливать несколько V-моделей одновременно.

// Demo.vue
export default {
  name: "Demo",
  props: {
    title:String,
    label:String
  },
  methods: {
    titleEmit(value) {
      this.$emit('update:title', value)
    },
    labelEmit(value) {
      this.$emit('update:label', value)
    }
  },
}

// 调用Demo.vue
<Demo v-model:title="" v-model:label="" />

10. Поддержка машинописного текста

рекомендуется v3Typescript,Typescriptне только поддерживаетES6Он также имеет вывод типов, который может помочь нам избежать многих ошибок типов в процессе разработки.Теперь, когда внешний интерфейс становится все более и более сложным,TypescriptОн может помочь приложению двигаться дальше, быть более совершенным с точки зрения ремонтопригодности и масштабируемости, а также принимать изменения.

Как создать приложение vue3+typescript?

1. Используйте vue-кли

yarn global add @vue/cli@next
# OR
npm install -g @vue/cli@next

// 下面按部就班的创建

2. Используйте vite (личная рекомендация, просто и легко)

yarn create vite-app my-vue-ts --template vue-ts

Снято! Неа

В этом разделе мы кратко разберем некоторые изменения в v3 с уровня приложения, не вникая в принцип и реализацию.

v3 Одно зеркало 999 карт!