目次
reactive
ref
总结
ホームページ ウェブフロントエンド Vue.js vue3のreactiveとrefの違いを詳しく解説(ソースコード解析)

vue3のreactiveとrefの違いを詳しく解説(ソースコード解析)

Aug 22, 2022 pm 07:53 PM
vue3 reactive ref

vue の reactive と ref の違いは何ですか?次の記事では、vue3 の reactive と ref の違いを徹底的に理解するために、ソース コードを詳しく説明します。お役に立てば幸いです。

vue3のreactiveとrefの違いを詳しく解説(ソースコード解析)

vue3 の日々の開発では、多くの人が自分の習慣に基づいてシャトルを使用していることがわかりましたreactiveorrefこれで要件を満たすことはできますが、その場合、すでに reactive があるのに、なぜ別の ref を設計する必要があるのでしょうか?実際のアプリケーション シナリオと 2 つの違いは何ですか?

そして、ref の基礎となるロジックに関して、ref の基礎となるロジックは依然として reactive であると言う人もいます。 ref の最下層は class であり、valueclass の単なる属性であると言う人もいます。そうですか?毛織物?これには何か根拠があるのでしょうか?

この質問では、今回はソースコードを深く掘り下げて、vue3のreactiverefの違いを徹底的に理解していきます。 (学習ビデオ共有: vue ビデオ チュートリアル )

ソース コードを見たくない場合は、後ろにスクロールして概要を読むことができます

reactive

ソースコードアドレス: packages/reactivity/reactive.ts

まず見てみましょうvue3 ReactiveFlags<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">// 标记目标对象 target 类型的 ReactiveFlags export const enum ReactiveFlags {   SKIP = '__v_skip',   IS_REACTIVE = '__v_isReactive',   IS_READONLY = '__v_isReadonly',   RAW = '__v_raw' } export interface Target {   [ReactiveFlags.SKIP]?: boolean          // 不做响应式处理的数据   [ReactiveFlags.IS_REACTIVE]?: boolean   // target 是否是响应式   [ReactiveFlags.IS_READONLY]?: boolean   // target 是否是只读   [ReactiveFlags.RAW]?: any               // 表示proxy 对应的源数据, target 已经是 proxy 对象时会有该属性 }</pre><div class="contentsignin">ログイン後にコピー</div></div>

reactive

export function reactive<t>(target: T): UnwrapNestedRefs<t>
export function reactive(target: object) {
  // if trying to observe a readonly proxy, return the readonly version.
  // 如果目标对象是一个只读的响应数据,则直接返回目标对象
  if (target && (target as Target)[ReactiveFlags.IS_READONLY]) {
    return target
  }
  // 创建 observe
  return createReactiveObject(
    target,
    false,
    mutableHandlers,
    mutableCollectionHandlers,
    reactiveMap
  )
}</t></t>
ログイン後にコピー
# で使用されるターゲットで## タイプ Objecttarget

reactive 関数は target オブジェクトを受け取ります。target オブジェクトが読み取り専用の場合は、戻り値が返されます。

読み取り専用でない場合は、

を直接渡します。 #createReactiveObject

長くなっても心配しないでください。まず createReactiveObject の完全なコードを投稿してください。セクションに分けて読んでみましょう <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">/**  *   * @param target 目标对象  * @param isReadonly 是否只读  * @param baseHandlers 基本类型的 handlers  * @param collectionHandlers 主要针对(set、map、weakSet、weakMap)的 handlers  * @param proxyMap  WeakMap数据结构  * @returns   */ function createReactiveObject(   target: Target,   isReadonly: boolean,   baseHandlers: ProxyHandler&lt;any&gt;,   collectionHandlers: ProxyHandler&lt;any&gt;,   proxyMap: WeakMap&lt;target&gt; ) {   // typeof 不是 object 类型的,在开发模式抛出警告,生产环境直接返回目标对象   if (!isObject(target)) {     if (__DEV__) {       console.warn(`value cannot be made reactive: ${String(target)}`)     }     return target   }   // target is already a Proxy, return it.   // exception: calling readonly() on a reactive object   // 已经是响应式的就直接返回(取ReactiveFlags.RAW 属性会返回true,因为进行reactive的过程中会用weakMap进行保存,   // 通过target能判断出是否有ReactiveFlags.RAW属性)   // 例外:对reactive对象进行readonly()   if (     target[ReactiveFlags.RAW] &amp;&amp;     !(isReadonly &amp;&amp; target[ReactiveFlags.IS_REACTIVE])   ) {     return target   }   // target already has corresponding Proxy   // 对已经Proxy的,则直接从WeakMap数据结构中取出这个Proxy对象   const existingProxy = proxyMap.get(target)   if (existingProxy) {     return existingProxy   }   // only a whitelist of value types can be observed.   // 只对targetTypeMap类型白名单中的类型进行响应式处理   const targetType = getTargetType(target)   if (targetType === TargetType.INVALID) {     return target   }   // proxy 代理 target   // (set、map、weakSet、weakMap) collectionHandlers   // (Object、Array) baseHandlers   const proxy = new Proxy(     target,     targetType === TargetType.COLLECTION ? collectionHandlers : baseHandlers   )   proxyMap.set(target, proxy)   return proxy }&lt;/target&gt;&lt;/any&gt;&lt;/any&gt;</pre><div class="contentsignin">ログイン後にコピー</div></div> まず、createReactiveObject が 5 つのパラメータを受け取ることがわかります。

  target: Target,
  isReadonly: boolean,
  baseHandlers: ProxyHandler<any>,
  collectionHandlers: ProxyHandler<any>,
  proxyMap: WeakMap<target></target></any></any>
ログイン後にコピー

target ターゲット オブジェクト

isReadonly 読み取られるかどうか-only

#baseHandlers 基本型ハンドラー 配列、オブジェクトの処理

collectionHandlers セット、マップ、weakSet、weakMap# の処理

##proxyMap

WeakMap データ構造には副作用関数が格納されます

ここでは主に

ReactiveFlags を使用します。RAWReactiveFlags.IS_REACTIVE

は、応答データである場合、オブジェクトは直接返されます

 if (
    target[ReactiveFlags.RAW] &&
    !(isReadonly && target[ReactiveFlags.IS_REACTIVE])
  ) {
    return target
  }
ログイン後にコピー
すでに Proxy
であるものについては、

WeakMap# から Proxy オブジェクトを直接取り出します## データ構造と戻り値 <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">  const existingProxy = proxyMap.get(target)   if (existingProxy) {     return existingProxy   }</pre><div class="contentsignin">ログイン後にコピー</div></div> ここでは、現在の target

の型が
Object

Array## であるかどうかを確認します。 #, Map, Set

,
WeakMap

, WeakSet、何もない場合は、直接応答処理を実行せずにオブジェクトを返します<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false"> // 只对targetTypeMap类型白名单中的类型进行响应式处理   const targetType = getTargetType(target)   if (targetType === TargetType.INVALID) {     return target   }</pre><div class="contentsignin">ログイン後にコピー</div></div> 検証タイプのロジック<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">function getTargetType(value: Target) {   return value[ReactiveFlags.SKIP] || !Object.isExtensible(value)     ? TargetType.INVALID     : targetTypeMap(toRawType(value)) } function targetTypeMap(rawType: string) {   switch (rawType) {     case 'Object':     case 'Array':       return TargetType.COMMON     case 'Map':     case 'Set':     case 'WeakMap':     case 'WeakSet':       return TargetType.COLLECTION     default:       return TargetType.INVALID   } }</pre><div class="contentsignin">ログイン後にコピー</div></div>すべての事前検証が完了したら、proxy AgenttargetObjectA を使用できます。 三項演算子

は、ここでさまざまな処理ロジックを実行するために使用されます

# を通じて

TargetType.COLLECTION

##(set,map,weakSet,weakMap) collectionHandlers#を使用します(オブジェクト、配列) baseHandlers

<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">// proxy 代理 target   // (set、map、weakSet、weakMap) collectionHandlers   // (Object、Array) baseHandlers   const proxy = new Proxy(     target,     targetType === TargetType.COLLECTION ? collectionHandlers : baseHandlers   )   proxyMap.set(target, proxy)   return proxy</pre><div class="contentsignin">ログイン後にコピー</div></div>## を使用します # これで、createReactiveObject の実行ロジックが非常に明確になりました

    まだ終わっていません。
  • createReactiveObject の最後の proxy
  • target をプロキシするにはどうすればよいですか?ここでは例として baseHandlers
  • を使用し、
baseHandlers
の奥深くに進み、

baseHandlers# を確認します。 #ソース コード アドレス: packages/reactivity/baseHandlers.tsreactive.ts では、合計 4 つのハンドラーが導入

import {
  mutableHandlers,
  readonlyHandlers,
  shallowReactiveHandlers,
  shallowReadonlyHandlers
} from './baseHandlers'
ログイン後にコピー

#mutableHandlers 変数処理##readonlyHandlers 読み取り専用処理

##shallowReactiveHandlers

浅い観察 処理 (ターゲット オブジェクトの第 1 レベルのプロパティのみを観察します)

shallowReadonlyHandlers

浅い観察 && 読み取り専用

We take
    例として mutableHandlers
  • <div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">// 可变处理 // const get = /*#__PURE__*/ createGetter() // const set = /*#__PURE__*/ createSetter() // get、has、ownKeys 会触发依赖收集 track() // set、deleteProperty 会触发更新 trigger() export const mutableHandlers: ProxyHandler&lt;object&gt; = {   get,                  // 用于拦截对象的读取属性操作   set,                  // 用于拦截对象的设置属性操作   deleteProperty,       // 用于拦截对象的删除属性操作   has,                  // 检查一个对象是否拥有某个属性   ownKeys               // 针对 getOwnPropertyNames,  getOwnPropertySymbols, keys 的代理方法 }&lt;/object&gt;</pre><div class="contentsignin">ログイン後にコピー</div></div>ここでの
  • get
  • set
  • createGetter()
  • createSetter()# に対応します。
  • ##createGetter()

最初にコードの完全版に移動します<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">/**  * 用于拦截对象的读取属性操作  * @param isReadonly 是否只读  * @param shallow 是否浅观察  * @returns   */ function createGetter(isReadonly = false, shallow = false) {   /**    * @param target 目标对象    * @param key 需要获取的值的键值    * @param receiver 如果遇到 setter,receiver 则为setter调用时的this值    */   return function get(target: Target, key: string | symbol, receiver: object) {     // ReactiveFlags 是在reactive中声明的枚举值,如果key是枚举值则直接返回对应的布尔值     if (key === ReactiveFlags.IS_REACTIVE) {       return !isReadonly     } else if (key === ReactiveFlags.IS_READONLY) {       return isReadonly     } else if (       // 如果key是raw  receiver 指向调用者,则直接返回目标对象。       // 这里判断是为了保证触发拦截 handle 的是 proxy 本身而不是 proxy 的继承者       // 触发拦的两种方式:一是访问 proxy 对象本身的属性,二是访问对象原型链上有 proxy 对象的对象的属性,因为查询会沿着原型链向下找       key === ReactiveFlags.RAW &amp;&amp;       receiver ===         (isReadonly           ? shallow             ? shallowReadonlyMap             : readonlyMap           : shallow           ? shallowReactiveMap           : reactiveMap         ).get(target)     ) {       return target     }     const targetIsArray = isArray(target)     // 如果目标对象 不为只读、是数组、key属于arrayInstrumentations:['includes', 'indexOf', 'lastIndexOf']方法之一,即触发了这三个方法之一     if (!isReadonly &amp;&amp; targetIsArray &amp;&amp; hasOwn(arrayInstrumentations, key)) {       // 通过 proxy 调用,arrayInstrumentations[key]的this一定指向 proxy       return Reflect.get(arrayInstrumentations, key, receiver)     }     const res = Reflect.get(target, key, receiver)     // 如果 key 是 symbol 内置方法,或者访问的是原型对象__proto__,直接返回结果,不收集依赖     if (isSymbol(key) ? builtInSymbols.has(key) : isNonTrackableKeys(key)) {       return res     }     // 不是只读类型的 target 就收集依赖。因为只读类型不会变化,无法触发 setter,也就会触发更新     if (!isReadonly) {       track(target, TrackOpTypes.GET, key)     }     // 如果是浅观察,不做递归转化,就是说对象有属性值还是对象的话不递归调用 reactive()     if (shallow) {       return res     }     // 如果get的结果是ref     if (isRef(res)) {       // ref unwrapping - does not apply for Array + integer key.       // 返回 ref.value,数组除外       const shouldUnwrap = !targetIsArray || !isIntegerKey(key)       return shouldUnwrap ? res.value : res     }     // 由于 proxy 只能代理一层,如果子元素是对象,需要递归继续代理     if (isObject(res)) {       // Convert returned value into a proxy as well. we do the isObject check       // here to avoid invalid value warning. Also need to lazy access readonly       // and reactive here to avoid circular dependency.       return isReadonly ? readonly(res) : reactive(res)     }     return res   } }</pre><div class="contentsignin">ログイン後にコピー</div></div> 長く見えますが、最終的には

track()

Dependency collectiontrack()Dependency collection の内容が多すぎます。と trigger() は一緒に更新をトリガーするため、別の記事を書きます。<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">/**  * 拦截对象的设置属性操作  * @param shallow 是否是浅观察  * @returns   */ function createSetter(shallow = false) {   /**    * @param target 目标对象    * @param key 设置的属性名称    * @param value 要改变的属性值    * @param receiver 如果遇到setter,receiver则为setter调用时的this值    */   return function set(     target: object,     key: string | symbol,     value: unknown,     receiver: object   ): boolean {     let oldValue = (target as any)[key]     // 如果模式不是浅观察模式     if (!shallow) {       // 拿新值和老值的原始值,因为新传入的值可能是响应式数据,如果直接和 target 上原始值比较是没有意义的       value = toRaw(value)       oldValue = toRaw(oldValue)       // 目标对象不是数组,旧值是ref,新值不是ref,则直接赋值,这里提到ref       if (!isArray(target) &amp;&amp; isRef(oldValue) &amp;&amp; !isRef(value)) {         oldValue.value = value         return true       }     } else {       // in shallow mode, objects are set as-is regardless of reactive or not     }     // 检查对象是否有这个属性     const hadKey =       isArray(target) &amp;&amp; isIntegerKey(key)         ? Number(key) &lt;p&gt;&lt;code&gt;trigger()&lt;/code&gt;触发更新&lt;/p&gt;&lt;h2 id=&quot;strong-ref-strong&quot;&gt;&lt;strong&gt;ref&lt;/strong&gt;&lt;/h2&gt;&lt;p&gt;源码地址:&lt;code&gt;packages/reactivity/src/ref.ts&lt;/code&gt;&lt;/p&gt;&lt;p&gt;接收一个可选&lt;code&gt;unknown&lt;/code&gt;,接着直接调用&lt;code&gt;createRef()&lt;/code&gt;&lt;/p&gt;&lt;pre class=&quot;brush:php;toolbar:false&quot;&gt;export function ref(value?: unknown) {   return createRef(value, false) }</pre><div class="contentsignin">ログイン後にコピー</div></div><p><img src="/static/imghw/default1.png" data-src="https://img.php.cn/upload/image/632/159/341/1661168925472417.png" class="lazy" title="1661168925472417.png" alt="vue3のreactiveとrefの違いを詳しく解説(ソースコード解析)"></p><p>与<code>ref的区别就是在调用createRef()时第二个值传的是true

export function shallowRef(value?: unknown) {
  return createRef(value, true)
}
ログイン後にコピー

看一下官方文档上对shallowRef的解释

vue3のreactiveとrefの違いを詳しく解説(ソースコード解析)

createRef

通过isRef()判断是否是ref数据,是则直接返回该数据,不是则通过new RefImpl创建ref数据

在创建时会传两个值一个是rawValue(原始值),一个是shallow(是否是浅观察),具体使用场景可看上面refshallowRef的介绍

function createRef(rawValue: unknown, shallow: boolean) {
  // 是否是 ref 数据
  if (isRef(rawValue)) {
    return rawValue
  }
  return new RefImpl(rawValue, shallow)
}
ログイン後にコピー
  • isRef()

通过__v_isRef只读属性判断是否是ref数据,此属性会在RefImpl创建ref数据时添加

export function isRef(r: any): r is Ref {
  return Boolean(r && r.__v_isRef === true)
}
ログイン後にコピー

RefImpl

class RefImpl<t> {
  private _value: T
  private _rawValue: T

  public dep?: Dep = undefined
  // 只读属性 __v_isRef 判断是否是ref数据的静态标识
  public readonly __v_isRef = true

  constructor(value: T, public readonly _shallow: boolean) {
    this._rawValue = _shallow ? value : toRaw(value)  // 非浅观察用toRaw()包裹原始值
    this._value = _shallow ? value : toReactive(value) // 非浅观察用toReactive()处理数据
  }

  get value() {
  // 依赖收集
    trackRefValue(this)
    return this._value
  }

  set value(newVal) {
    newVal = this._shallow ? newVal : toRaw(newVal) // 非浅观察用toRaw()包裹值
    // 两个值不相等
    if (hasChanged(newVal, this._rawValue)) {
      this._rawValue = newVal
      this._value = this._shallow ? newVal : toReactive(newVal)
      triggerRefValue(this, newVal) // 触发依赖,派发更新
    }
  }
}</t>
ログイン後にコピー

根据RefImpl我们可以看到ref的底层逻辑,如果是对象确实会使用reactive进行处理,并且ref的创建使用的也是RefImpl class实例,value只是RefImpl的属性

在我们访问设置 ref的value值时,也分别是通过getset拦截进行依赖收集派发更新

  • toReactive

我们来看一下toReactive()这个方法,在RefImpl中创建ref数据时会调用toReactive()方法,这里会先判断传进来的值是不是对象,如果是就用reactive()包裹,否则就返回其本身

export const toReactive = <t>(value: T): T =>
  isObject(value) ? reactive(value) : value</t>
ログイン後にコピー
  • trackRefValue

ref的依赖收集方法

export function trackRefValue(ref: RefBase<any>) {
  if (isTracking()) {
    ref = toRaw(ref)
    if (!ref.dep) {
      ref.dep = createDep()
    }
    if (__DEV__) {
      trackEffects(ref.dep, {
        target: ref,
        type: TrackOpTypes.GET,
        key: 'value'
      })
    } else {
      trackEffects(ref.dep)
    }
  }
}</any>
ログイン後にコピー
  • triggerRefValue

ref的派发更新方法

export function triggerRefValue(ref: RefBase<any>, newVal?: any) {
  ref = toRaw(ref)
  if (ref.dep) {
    if (__DEV__) {
      triggerEffects(ref.dep, {
        target: ref,
        type: TriggerOpTypes.SET,
        key: 'value',
        newValue: newVal
      })
    } else {
      triggerEffects(ref.dep)
    }
  }
}</any>
ログイン後にコピー

总结

看完reactiveref源码,相信对本文一开始的几个问题也都有了答案,这里也总结了几个问题:

  • 问:ref的底层逻辑是什么,具体是如何实现的

答:ref底层会通过 new RefImpl()来创造ref数据,在new RefImpl()会首先给数据添加__v_isRef只读属性用来标识ref数据。而后判断传入的值是否是对象,如果是对象则使用toReactive()处理成reactive,并将值赋给RefImpl()value属性上。在访问设置ref数据的value时会分别触发依赖收集派发更新流程。


  • 问:ref底层是否会使用reactive处理数据

答:RefImpl中非浅观察会调用toReactive()方法处理数据,toReactive()中会先判断传入的值是不是一个对象,如果是对象则使用reactive进行处理,不是则直接返回值本身。


  • 问:为什么已经有了reactive还需要在设计一个ref呢?

答: 因为vue3响应式方案使用的是proxy,而proxy的代理目标必须是非原始值,没有任何方式能去拦截对原始值的操作,所以就需要一层对象作为包裹,间接实现原始值的响应式方案。


  • 问:为什么ref数据必须要有个value属性,访问ref数据必须要通过.value的方式呢?

答:这是因为要解决响应式丢失的问题,举个例子:

// obj是响应式数据
const obj = reactive({ foo: 1, bar: 2 })

// newObj 对象下具有与 obj对象同名的属性,并且每个属性值都是一个对象
// 该对象具有一个访问器属性 value,当读取 value的值时,其实读取的是 obj 对象下相应的属性值 
const newObj = {
    foo: {
        get value() {
            return obj.foo
        }
    },
    bar: {
        get value() {
            return obj.bar
        }
    }
}

effect(() => {
    // 在副作用函数内通过新对象 newObj 读取 foo 的属性值
    console.log(newObj.foo)
})
// 正常触发响应
obj.foo = 100
ログイン後にコピー

可以看到,在现在的newObj对象下,具有与obj对象同名的属性,而且每个属性的值都是一个对象,例如foo 属性的值是:

{
    get value() {
        return obj.foo
    }
}
ログイン後にコピー

该对象有一个访问器属性value,当读取value的值时,最终读取的是响应式数据obj下的同名属性值。也就是说,当在副作用函数内读取newObj.foo时,等价于间接读取了obj.foo的值。这样响应式数据就能够与副作用函数建立响应联系

(学習ビデオ共有: Web フロントエンド開発基本プログラミング ビデオ)

以上がvue3のreactiveとrefの違いを詳しく解説(ソースコード解析)の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

AI Hentai Generator

AI Hentai Generator

AIヘンタイを無料で生成します。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

vue3+vite: src に画像を動的にインポートするために require を使用するときのエラーを解決する方法 vue3+vite: src に画像を動的にインポートするために require を使用するときのエラーを解決する方法 May 21, 2023 pm 03:16 PM

vue3+vite:src は、イメージとエラー レポートと解決策を動的にインポートするために require を使用します。vue3+vite は複数のイメージを動的にインポートします。vue3。TypeScript 開発を使用している場合、イメージを導入するために require のエラー メッセージが表示されます。requireisnotdefined は使用できません。 vue2 のような imgUrl:require(' .../assets/test.png') は、typescript が require をサポートしていないため、インポートされます。そのため、import が使用されます。解決方法は次のとおりです: awaitimport を使用します

vue3 プロジェクトで tinymce を使用する方法 vue3 プロジェクトで tinymce を使用する方法 May 19, 2023 pm 08:40 PM

tinymce はフル機能のリッチ テキスト エディター プラグインですが、tinymce を vue に導入するのは他の Vue リッチ テキスト プラグインほどスムーズではありません。tinymce 自体は Vue には適しておらず、@tinymce/tinymce-vue を導入する必要があります。外国のリッチテキストプラグインであり、中国語版を通過していないため、公式 Web サイトから翻訳パッケージをダウンロードする必要があります (ファイアウォールをバイパスする必要がある場合があります)。 1. 関連する依存関係をインストールします npminstalltinymce-Snpminstall@tinymce/tinymce-vue-S2. 中国語パッケージをダウンロードします 3. スキンと中国語パッケージを導入します. プロジェクトのパブリック フォルダーに新しい tinymce フォルダーを作成し、

Vue3 でページの部分的なコンテンツを更新する方法 Vue3 でページの部分的なコンテンツを更新する方法 May 26, 2023 pm 05:31 PM

ページの部分的な更新を実現するには、ローカル コンポーネント (dom) の再レンダリングを実装するだけで済みます。 Vue でこの効果を実現する最も簡単な方法は、v-if ディレクティブを使用することです。 Vue2 では、v-if 命令を使用してローカル dom を再レンダリングすることに加えて、新しい空のコンポーネントを作成することもできます。ローカル ページを更新する必要がある場合は、この空のコンポーネント ページにジャンプしてから、再びジャンプします。 beforeRouteEnter ガードを空白のコンポーネントに配置します。元のページ。以下の図に示すように、Vue3.X の更新ボタンをクリックして赤枠内の DOM を再読み込みし、対応する読み込みステータスを表示する方法を示します。 Vue3.X の scriptsetup 構文のコンポーネントのガードには o しかないので、

Vue3 がマークダウンを解析し、コードのハイライトを実装する方法 Vue3 がマークダウンを解析し、コードのハイライトを実装する方法 May 20, 2023 pm 04:16 PM

Vue はブログ フロントエンドを実装しており、マークダウン解析を実装する必要があり、コードがある場合はコードのハイライトを実装する必要があります。 Vue には、markdown-it、vue-markdown-loader、marked、vue-markdown など、マークダウン解析ライブラリが多数あります。これらのライブラリはすべて非常に似ています。ここではMarkedが使用され、コード強調表示ライブラリとしてhighlight.jsが使用されます。 1. 依存ライブラリをインストールする vue プロジェクトの下でコマンド ウィンドウを開き、次のコマンド npminstallmarked-save//marked を入力して、マークダウンを htmlnpmins に変換します。

Vue3 でアバターを選択してトリミングする方法 Vue3 でアバターを選択してトリミングする方法 May 29, 2023 am 10:22 AM

最終的な効果は、VueCropper コンポーネントのyarnaddvue-cropper@next をインストールすることです。上記のインストール値は Vue3 用です。Vue2 の場合、または他の方法を参照したい場合は、公式 npm アドレス: 公式チュートリアルにアクセスしてください。また、コンポーネント内で参照して使用するのも非常に簡単です。必要なのは、対応するコンポーネントとそのスタイル ファイルを導入することだけです。ここではグローバルに参照しませんが、import{userInfoByRequest}from'../js/api を導入するだけです。 ' コンポーネント ファイルにインポートします。import{VueCropper}from'vue-cropper&

vue3+ts+axios+pinia を使用して無意味なリフレッシュを実現する方法 vue3+ts+axios+pinia を使用して無意味なリフレッシュを実現する方法 May 25, 2023 pm 03:37 PM

vue3+ts+axios+pinia で無意味なリフレッシュを実現 1. まず、プロジェクト内の aiXos と pinianpmipinia をダウンロードします--savenpminstallaxios--save2. axios リクエストをカプセル化-----ダウンロード js-cookienpmiJS-cookie-s// aixosimporttype{AxiosRequestConfig , AxiosResponse}from"axios";importaxiosfrom'axios';import{ElMess

Vue3 の再利用可能なコンポーネントの使用方法 Vue3 の再利用可能なコンポーネントの使用方法 May 20, 2023 pm 07:25 PM

はじめに vue であれ、react であれ、複数の繰り返しコードに遭遇した場合、ファイルを冗長なコードの束で埋めるのではなく、これらのコードを再利用する方法を考えます。実際、vue と React はどちらもコンポーネントを抽出することで再利用を実現できますが、小さなコードの断片に遭遇し、別のファイルを抽出したくない場合は、それに比べて、React は同じファイル内で対応するウィジェットを宣言して使用できます。または、次のような renderfunction を通じて実装します。 constDemo:FC=({msg})=>{returndemomsgis{msg}}constApp:FC=()=>{return(

DefineCustomElement を使用して Vue3 でコンポーネントを定義する方法 DefineCustomElement を使用して Vue3 でコンポーネントを定義する方法 May 28, 2023 am 11:29 AM

Vue を使用してカスタム要素を構築する WebComponents は、開発者が再利用可能なカスタム要素 (カスタム要素) を作成できるようにする一連の Web ネイティブ API の総称です。カスタム要素の主な利点は、フレームワークがなくても、任意のフレームワークで使用できることです。これらは、異なるフロントエンド テクノロジ スタックを使用している可能性のあるエンド ユーザーをターゲットにする場合、または最終アプリケーションを使用するコンポーネントの実装の詳細から切り離したい場合に最適です。 Vue と WebComponents は補完的なテクノロジであり、Vue はカスタム要素の使用と作成に対する優れたサポートを提供します。カスタム要素を既存の Vue アプリケーションに統合したり、Vue を使用してビルドしたりできます。

See all articles