Vue中使用props 创建计算属性,当props发生变化时 计算属性没有发生变化?

//homeTag2.js

//使用es module进行import

import { createApp, ref, computed, reactive } from "vue"

const HomeTag = {

props:['id','title'],

setup(props,context) {

//将Props中的属性 保存为私有属性

const homeTagId= ref(props.id)

//组件自身属性

let homeTagName = ref("homeTagName")

//组件使用props创建的计算属性

const normalizedId= computed(()=>{

console.log(props.id*1000)

return Math.floor(Math.random() * 10*props.id) + 1

})

return {

homeTagName,

homeTagId,

normalizedId

}

},

template: `<div> propsId:{{id}},{{title}},homeTagId:{{homeTagId}},normalizedId:{{normalizedId}}</div> `

};

//使用es module 进行你export

export default HomeTag

//index.html

<!DOCTYPE html>

<html lang="en">

<body>

<div id="app">

<p>{{name}}</p>

<home-tag v-bind="post"></home-tag>

<button @click="btnClick"> click</button>

</div>

</body>

<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>

<script type="importmap">

{"imports":{

"vue":"https://unpkg.com/vue@3/dist/vue.esm-browser.js"

}}

</script>

<script type="module" src="./homeTag2.js">

</script>

<script type="module">

import HomeTag from "./homeTag2.js"

const { createApp, ref, reactive } = Vue

console.log("createApp", createApp)

//应用实例

var appVueInstance = createApp({

setup() {

let name = ref("abc")

let aritcle = { id: 1, title: "My Journey with vue" };

const post = ref(aritcle)

console.log("post",post)

console.log("post.value",post.value)

console.log("article",aritcle)

function btnClick() {

// aritcle.id=3;

post.value.id=Math.random()

console.log("post.value",post.value)

}

return {

name,

post,

btnClick

}

}

})

//注册组件

appVueInstance.component("home-tag", HomeTag)

appVueInstance.mount("#app")

</script>

</html>

index.html 中通过点击按钮每次 随机更新 post的id属性值。 而post对象被 v-bind 到 子组件home-tag的 props中的id和title属性中。

home-tag子组件中存在计算属性normalizedId 依赖于props的id属性。

因此 理论上每次 点击 post的id的更新会导致normalizedId 的值一起变化。

问题: 实际运行 normalizedId 的值没有变化。


回答:

问题基本已经可以锁定在两种模块加载方式混用上了。

题主这里是 ESM + 普通 JS 模块混用的,所以出现了这种奇怪的现象。两种改法可以解决此问题。

第一种见原题评论区,把 index.html 改造成完全的 ESM 形式。

第二种是把 index.htmlhomeTag2.js 都改造成完全的普通 JS 形式:

<!-- index.html -->

<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>

<script src="./homeTag2.js"></script>

<script>

const { createApp, ref, reactive } = Vue;

const HomeTag = window.HomeTag;

// 略

</script>

const { ref, computed, reactive } = Vue;

const HomeTag = {

// 略

};

window.HomeTag = HomeTag;


只要像原题中 index.html 里用的是全局变量 Vue、homeTag2.js 用的是模块 vue 这样的混用,就会出现 computed 不触发的问题。

具体原因未知,可能跟依赖收集的作用域有关,混用的时候两者不在同一个作用域下。这个具体咋回事儿得看下源码了,感兴趣的话题主可以自己尝试跟踪一下,我已经给缩小范围了。


回答:

没有复现你的问题——Playground


回答:

看了一下项目
你用watch:

import { watch, computed } from 'vue';

props: ['id'],

setup(props) {

const normalizedId = ref(0);

watch(

() => props.id,

(newId, oldId) => {

normalizedId.value = Math.floor(Math.random() * 10 * newId) + 1;

},

{ immediate: true }

);

// ...

}

或者不用v-bind解构对象:

在父组件里:

<home-tag :post="post"></home-tag>

在子组件里:

props: ['post'],

setup(props) {

const normalizedId = computed(() => {

return Math.floor(Math.random() * 10 * props.post.id) + 1;

});

// ...

}:

以上是 Vue中使用props 创建计算属性,当props发生变化时 计算属性没有发生变化? 的全部内容, 来源链接: utcz.com/p/934859.html

回到顶部