Vue 3.0 function-based API尝鲜(二):配置与启动

关键词:配置、setup()

开始用之前,得先配置一下环境。这个的“环境”配置起来也简单,只需要在先通过npm/yarn安装依赖,然后在main.js(或者main.ts)里加上这么一小段就行了:

// main.js
import { plugin } from 'vue-function-api'
Vue.use(plugin) // 别漏了这句

说起来简单,不过要是忘了引入,可能会出现属性/方法未定义的报错(也就是Property or method is not defined on the instance but referenced during render这个报错),导致后续的工作都无法开展。尤其是这里必须显式地使用Vue.use()导入,这一点容易被忽略。虽然文档上已经很明确地写了:

您必须显式地通过 Vue.use() 来安装 vue-function-api

值得一提的是,这个库同样支持在<script>标签里直接引入,就跟Vue本体一样是个UMD库,这个让我吃惊不小;不过想想也挺正常的。

<script src="https://unpkg.com/vue-function-api/dist/vue-function-api.umd.js"></script>

通过全局变量 window.vueFunctionApi 来使用。

至于具体使用么,在每个单文件组件SFC的<script>标签里import,然后使用就好了。不过用法上稍微有点区别,第一个是API全部换成函数式的了,另一个就是没有了data(),可响应属性的初始化以及所有的生命周期钩子都要放到新加的setup()里。这是官方的例子:

<script>
  import Vue from 'vue';
  import { value, computed, watch, onMounted } from 'vue-function-api'

  export default {
    setup() {
      // reactive state
      const count = value(0);
      // computed state
      const plusOne = computed(() => count.value + 1);
      // method
      const increment = () => {
        count.value++;
      };
      // watch
      watch(
        () => count.value * 2,
        val => {
          console.log(`count * 2 is ${val}`);
        }
      );
      // lifecycle
      onMounted(() => {
        console.log(`mounted`);
      });
      // expose bindings on render context
      return {
        count,
        plusOne,
        increment,
      };
    },
  };
</script>

可以看到,变化还是挺大的。里面的具体内容后续会单独提出来说,目前需要强调的是写法上的变化:可响应的数据和需要调用的方法(对应于之前的data()methods)变成了setup()的返回值,不然无法在模板里调用。

看起来可能确实不太习惯,不过这里改用setup()有一个额外的好处:更符合写JavaScript的习惯。

看看官方文档咋说的:

setup(props: Props, context: Context): Object|undefined

组件现在接受一个新的 setup 选项,在这里我们利用函数 api 进行组件逻辑设置。

setup() 中不可以使用 this 访问当前组件实例, 我们可以通过 setup 的第二个参数 context 来访问 vue2.x API 中实例上的属性。

const MyComponent = {
	props: {
		name: String
	},
	setup(props, context) {
		console.log(props.name);
		// context.attrs
		// context.slots
		// context.refs
		// context.emit
        // context.parent
        // context.root
   }
}

这里的context取代了this,成为了实例的“指针”;而this直接指向了undefined。至于为什么要这么设计,按照官方说法,是为了避免错误使用this:

setup() {
  function onClick() {
    this // 这里的this指向并不会是预期中的调用者
  }
}

这里的this指向谁?我也不知道,完全取决于在什么context下调用这个函数。通常情况下,如果是在setup里调用,会是undefined;如果是用v-on绑定,然后等待触发,因为Vue会自己进行代理,通常情况下,这个函数会绑定到不同的context(从调用栈来分析,似乎一般是null,比如绑定了click事件;或者一个Proxy对象,比如绑定了按键事件,因为Vue3是基于Proxy的),反正不可能是触发事件的那个DOM元素。

文档里也提到,setup() 中不能使用 this 访问当前组件实例,所以很多在2.x里用到的基于this的用法都会发生改变,比如$refs$store$router。这些之前绑定在根实例上的内容,需要通过context.root获取。这些后面会提到。

另外,setup()只会在创建时被调用一次。

还有一个,这里的props和context都是可响应的,会确保和修改同步。按照尤大的原话来说:

需要留意的是这里传进来的 props 对象是响应式的 —— 它可以被当作数据源去观测,当后续 props 发生变动时它也会被框架内部同步更新。但对于用户代码来说,它是不可修改的(会导致警告)。

不过这个“数据源”说得实在是有点模糊。事实上,props是不能作为watch的数据源使用的,因为watch的文档里提到,只能观测函数、包装对象和包含前两者的数组。我觉得,尤大在这里想表达的意思,应该是和2.x的文档里一致的:

所有的 prop 都使得其父子 prop 之间形成了一个单向下行绑定:父级 prop 的更新会向下流动到子组件中,但是反过来则不行。这样会防止从子组件意外改变父级组件的状态,从而导致你的应用的数据流向难以理解。

也就是说,是一个可以动态响应的属性。我感觉Vue的核心思想还是数据驱动,对数据流的控制是很重视的。虽然实现上是双向绑定,但是数据流最好还是单向的。正如文档里提到的那样,实际使用的时候其实也没有必要修改props。如果确实需要修改传过来的props,也是保存到组件内部,作为组件本身的属性进行修改。

至于包装对象呢,放到后面说。

目录

Vue 3.0 function-based API尝鲜(一):前言

Vue 3.0 function-based API尝鲜(三):包装对象

Vue 3.0 function-based API尝鲜(四):值得一提的watch

Vue 3.0 function-based API尝鲜(五):生命周期

Vue 3.0 function-based API尝鲜(六):组件间通信

Vue 3.0 function-based API尝鲜(七):This与Refs

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Vue3.0中的组件高级功能包括保持动态组件状态和引用DOM元素。 保持动态组件状态的方法是使用Vue内置的<keep-alive>组件。通过将动态组件包裹在<keep-alive>标签中,可以在切换动态组件时保持组件的状态。例如: ```html <keep-alive> <component :is="comName"></component> </keep-alive> ``` 在这个例子中,comName是一个data属性,用于指定当前要渲染的组件的名称。通过在<component>标签中使用:is属性,可以动态地指定要渲染的组件。 引用DOM元素的方法是使用ref属性。通过给DOM元素添加ref属性,可以在组件中通过$refs属性获取对DOM元素的引用。例如: ```html <template> <h3>MyRef组件</h3> <button @click="getRef">获取$refs引用</button> </template> <script> export default { methods: { getRef() { console.log(this.$refs) // $refs指向一个空对象,需要在DOM元素上添加ref属性 } } } </script> ``` 在这个例子中,点击按钮后,调用getRef方法可以在控制台上输出当前组件实例对象this。通过this.$refs可以访问到DOM元素的引用。 以上就是Vue3.0中组件高级功能的两个示例,分别是保持动态组件状态和引用DOM元素。希望能对你有所帮助。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [Vue3.0----组件高级【下】(第五章)](https://blog.csdn.net/QQ675396947/article/details/127486948)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值