美文网首页react & vue & angular
Vue3.0 基础学习自我理解(三)

Vue3.0 基础学习自我理解(三)

作者: coderhzc | 来源:发表于2022-07-03 16:57 被阅读0次

1. setup 函数有哪些参数--props

1.1 父组件App.vue

<template>
  <div>
    <home-page id="aaa" class="bbb" :message="'哈哈我是胡振楚'">
      <template>
        <div>我是胡振楚</div>
      </template>
    </home-page>
  </div>
</template>
<script>
import HomePage from "@/01_setup函数的基本使用/01_setup 函数有哪些参数--props.vue";

export default {
  name: "App",
  components: {
    HomePage,
  },
};
</script>

<style>
</style>

1.2 子组件

<template>
  <div>Home Page</div>
  <h2>{{ message }}</h2>
  <h2>{{ messageInfo }}</h2>
</template>

<script>
export default {
  name: "homePage",
  props: {
    //  在Vue3.0 中这个也是需要写的
    message: {
      type: String,
      required: true,
    },
  },
  /**
   *
   * setup 函数有哪些参数? 他主要是有两个参数
   *   -- 第一个参数: props 父组件传递过来的属性
   *   -- 第二个参数: context
   *
   * **/
  setup(props, context) {
    console.log(props); // 从父组件中传递过来的数据
    console.log(context);
    const messageInfo = props.message

    return {
      messageInfo
    }
  },

  // setup函数有什么样的返回值
};
</script>

<style>
</style>

实际截图:

image.png

2.setup 函数有哪些参数--context

2.1 子组件

<template>
  <div>Home Page</div>
</template>

<script>
export default {
  name: "homePage",

  /**
   *
   * setup 函数有哪些参数? 他主要是有两个参数
   *   -- 第二个参数: context: 参数是context,我们也称之为是一个SetupContext,它里面包含三个属性:
   *                  -- 1. attrs:所有的非prop的attribute;
   *                  -- 2. slots:父组件传递过来的插槽
   *                  -- 3. emit:当我们组件内部需要发出事件时会用到emit
   * **/
  setup(props, context) {
    console.log(context);
    // 1.attrs:所有的非prop的attribute;
    console.log(context.attrs); // {id: 'aaa', class: 'bbb', __vInternal: 1}
    // 2.slots:父组件传递过来的插槽
    console.log(context.slots);

    // 3. emit 事件
    console.log(context.emit);
  },
};
</script>

<style>
</style>

实际截图

image.png

3.setup函数的返回值

<template>
  <div>
    <h1>setup函数的返回值</h1>
    <h2>{{ message }}</h2>
    <hr />
    <h2>当前计数: {{ counter }}</h2>
    <!-- 1. 如何在setup中去定义一个功能函数 -->
    <button @click="add"> + 1 </button>
  </div>
</template>

<script>
export default {
  name: "HomePage",
  setup() {
    /**
     * setup函数的返回值,它的返回值用来做什么呢?
     *     -- 也就是说我们可以通过setup的返回值来替代data选项;
     *     -- setup的返回值可以在模板template中被使用;
     *
     * **/
    // 1. 如何在setup中去定义一个功能函数
    let counter = 100
    const add = ()=> {
      counter ++; // 这种直接++ 是不会更新界面的
    }
    return {
      message: "Hello Setup function!",
      counter,
      add
    };
  },
};
</script>

<style>
</style>

实际截图

image.png

4. setup 函数中没有this

<template>
  <h1>setup不可以使用this</h1>
</template>

<script>

export default {
  /**
   * setup不可以使用this
   *  -- 表达的含义是this并没有指向当前组件实例;
   * 
   *  -- 并且在setup被调用之前,data、computed、methods等都没有被解析;
   * 
   *  -- 在setup中你应该避免使用this,因为他不会找到组件实例.setup的调用发生在data property,computed 或methods被解析之前,
   *     所以他们无法在setup中被获取
   * 
   *  -- 所以无法在setup中获取this;
   * **/
  setup() {
    console.log(this); // undefined
  }
}
</script>

<style>

</style>

实际截图

image.png

5.setup函数中实现响应式-Reactive的使用

<template>
  <div>
    <!-- PS: 这种return出去的是一个对象,所以上面template模板中的话需要 state.counter取值 -->
    <!-- <h1>当前计数:{{ state }}</h1> -->
    <h1>当前计数:{{ state.counter }}</h1>
    <button @click="add">实现 + 1 的响应式处理</button>
  </div>
</template>

<script>
// 1.想要是响应式的话需要引入一个vue内置函数-reactive函数
import { reactive } from "vue";
export default {
  setup() {
    // 1. 使用这个reactive内置函数
    const state = reactive({
      counter: 100,
    });

    console.log(state); // 这种打印拿到的是一个对象 {counter: 100}
    // 定义一个 add 函数
    const add = () => {
      state.counter++; // 这种就可以做到响应式的了
    };

    return {
      state, // 这种return出去的是一个对象,所以上面template模板中的话需要 state.counter取值
      add,
    };
  },
};
</script>

<style>
</style>

实际截图

image.png

6.setup函数中实现响应式-Ref的使用

<template>
  <div>
    <!-- 这个地方 其实vue 做了一个解包的过程,不需要state.value 直接写state他会给你自动解包 -->
    <!-- 在template中是有自动解包功能的,在setup中是没有自动解包功能的 -->
    <h1>当前计数:{{ state }}</h1>
    <button @click="add">实现 + 1 的响应式处理</button>
  </div>
</template>

<script>
// 1.想要是响应式的话需要引入一个vue内置函数-Ref函数
import { ref } from "vue";
export default {
  setup() {
    // 1. 使用这个Ref内置函数
    let state = ref(100);

    console.log(state); // 这种打印拿到的是一个对象 {__v_isShallow: false, dep: undefined, __v_isRef: true, _rawValue: 100, _value: 100}

    // 定义一个 add 函数
    const add = () => {
      // PS: 在template中是有自动解包功能的,在setup中是没有自动解包功能的
      state.value++; // 这种就可以做到响应式的了,所以这里必须要state.value
    };

    return {
      state,
      add,
    };
  },
};
</script>

<style>
</style>

实际截图

image.png

7.setup函数-refAPI浅层解包

<template>
  <div>
    <h1>当前计数:{{ counter }}</h1>
    <button @click="add">实现 + 1 的响应式处理</button>


    <hr>
    <!-- 2. 理解浅层解包,如果里面套的层级超过两层就不会自动解包了,这种情况就叫做浅层解包 -->
    <h1>理解浅层解包:{{info}}</h1>
  </div>
</template>

<script>
import { ref } from "vue";
export default {
  setup() {
    // 1.属于浅层解包
    let counter = ref(100);

    // 2. 理解浅层解包 把counter放入到一个info对象中
    let info = {
      counter
    }
    const add = () => {
      counter.value++;
    };

    return {
      counter,
      info, // 2. 理解浅层解包,如果里面套的层级超过两层就不会自动解包了,这种情况就叫做浅层解包 
      add,
    };
  },
};


/**
 * 
 * PS: ref的解包只能是一个浅层的解包
 * 
 * 
 * **/
</script>

<style>
</style>

实际截图

image.png

8.setup函数-refAPI浅层解包-可以深层解包

<template>
  <div>
    <h1>当前计数:{{ counter }}</h1>
    <button @click="add">实现 + 1 的响应式处理</button>

    <hr />
    <!-- 2. 理解浅层解包,如果里面套的层级超过两层就不会自动解包了,这种情况就叫做浅层解包 -->
    <h1>理解浅层解包:{{ info }}</h1>


    <!-- 3.这种情况是可以解包的 -->
    <h1>使用reactive是可以解包的:{{ reactiveInfo.counter }}</h1>
  </div>
</template>

<script>
import { reactive, ref } from "vue";
export default {
  setup() {
    // 1.属于浅层解包
    let counter = ref(100);

    // 2. 理解浅层解包 把counter放入到一个info对象中
    let info = {
      counter,
    };
    // 3.这种情况是可以解包的
    const reactiveInfo = reactive({
      counter,
    });
    const add = () => {
      counter.value++;
    };

    return {
      counter,
      info, // 2. 理解浅层解包,如果里面套的层级超过两层就不会自动解包了,这种情况就叫做浅层解包
      add,
      reactiveInfo, // 3.这种情况是可以解包的
    };
  },
};

/**
 *
 * PS: ref的解包只能是一个浅层的解包
 *
 *
 * **/
</script>

<style>
</style>

实际截图

image.png

9. setup函数-readOnly

<template>
  <div>
    <h2>{{ readonlyInfo1.name }}</h2>
    <button @click="updateState1">readonly只读方法一</button>
    <hr />

    <h2>{{ readonlyInfo2.name }}</h2>
    <button @click="updateState2">readonly只读方法二</button>

    <hr />

    <h2>{{ readonlyInfo3 }}</h2>
    <button @click="updateState3">readonly只读方法三</button>
  </div>
</template>

<script>
/**
 * 1. 只读方法 readonly
 *    需求: 我们通过reactive或者ref可以获取到一个响应式的对象,但是某些情况下,我们传入给其他地方(组件)的这个
 * 响应式对象希望在另外一个地方(组件)被使用,但是不能被修改,这个时候如何防止这种情况的出现呢?
 *    -- Vue3为我们提供了readonly的方法;
 *
 *    readonly会返回原生对象的只读代理(也就是它依然是一个Proxy,这是一个proxy的set方法被劫持,并且不
 * 能对其进行修改);
 *
 *
 * 2.在开发中常见的readonly方法会传入三个类型的参数:
 *   -- 类型一:普通对象;
 *   -- 类型二:reactive返回的对象;
 *   -- 类型三:ref的对象;
 * **/
import { ref, readonly, reactive } from "vue";
export default {
  setup() {
    // 1. 普通对象
    const info1 = { name: "hzc" };
    const readonlyInfo1 = readonly(info1);

    const updateState1 = () => {
      readonlyInfo1.name = "chuchuhu"; // 报警告:Set operation on key "name" failed: target is readonly. {name: 'hzc'}
    };

    // 2.响应式对象
    const info2 = reactive({
      name: "huzhenchu",
    });

    const readonlyInfo2 = readonly(info2);
    const updateState2 = () => {
      readonlyInfo2.name = "胡振楚"; // 报警告: Set operation on key "name" failed: target is readonly. Proxy {name: 'huzhenchu'}
    };

    // 2.响应式对象
    const info3 = ref("huzhenchu");

    const readonlyInfo3 = readonly(info3);
    const updateState3 = () => {
      readonlyInfo3.value = "胡振楚"; // 报警告:Set operation on key "value" failed: target is readonly.
    };
    /**PS: 不管你是响应式的还是普通的对象 只要是用了readonly的话他就不可以修改**/
    return {
      updateState1,
      updateState2,

      readonlyInfo1,
      readonlyInfo2,

      readonlyInfo3,
      updateState3,
    };
  },
};
</script>

<style>
</style>

实际截图

image.png

相关文章

网友评论

    本文标题:Vue3.0 基础学习自我理解(三)

    本文链接:https://www.haomeiwen.com/subject/xltrbrtx.html