Vue3.0 初体验

1. createApp

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Vue3.0</title>
  </head>
  <body>
    <div id="app">
      <h1 :title="title">{{title}}</h1>
      <course v-model="inputVal" @add="addCourse"></course>
      <p>{{ list.toString() }}</p>
    </div>
    <script src="https://unpkg.com/vue@next"></script>

    <script type="text/x-template" id="course">
        <input :value="modelValue" @input="$emit('update:modelValue',$event.target.value)" placeholder="添加课程" />
        <button @click="$emit('add')">添加数据</button>
    </script> 
    <script>
      const Course= {
          template: "#course",
          props: {
            modelValue:{
              type: String,
              required: true
            }
          },
          emits: ["add","update:modelValue"]
      }  
      Vue.createApp({
        components:{
            course: Course
        },  
        data() {
          return {
            title: "缪冬冬",
            list:[],
            inputVal:"默认值"
          };
        },
        methods: {
            addCourse() {
                this.list.push(this.inputVal)
            }
        },
      }).mount("#app");
    </script>
  </body>
</html>

2.setup

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Vue Composition Api</title>
  </head>
  <body>
    <div id="app">
      <h2>{{ state.title }}</h2>
      <h2>数值ref: {{count}}</h2>
      <comp title="666" desc="555"></comp>
    </div>
    <script src="https://unpkg.com/vue@next"></script>
    <script type="text/x-template" id="com">
      <input v-model="val" placeholder="请输入内容" />
      <button @click="addItem">添加内容</button>
      <ul>
          <li v-for="(item,i) in list" :key="i">{{item}}</li>
      </ul>
    </script>
    <script>
      const { reactive, onMounted, ref, toRefs } = Vue;
      const Comp = {
        template: "#com",
        props: ["title"],
        setup(props, ctx) {
          console.log(props, ctx);
          const { attrs } = ctx;

          const state = reactive({
            val: props.title,
            list: [attrs.desc],
          });

          function addItem() {
            state.list.push(state.val);
          }

          return {
            ...toRefs(state),
            addItem,
          };
        },
      };

      const app = Vue.createApp({
        components: {
          Comp,
        },
        setup() {
          const state = reactive({
            title: "默认值",
          });

          onMounted(() => {
            console.log(document.getElementById("app"));
            setTimeout(() => {
              state.title = "修改的值";
            }, 2000);
          });

          const count = ref(0);

          setInterval(() => {
            count.value++;
          }, 1000);

          return {
            state,
            count,
          };
        },
      }).mount("#app");
    </script>
  </body>
</html>

3.watch

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <div id="app">
      <p>count的值: --- {{count}}</p>
      <p>count的值: --- {{newCount}}</p>
      <input v-model="val" /><button @click="addCourse">添加课程</button>
      <p>{{valDesc}}</p>
      <ul>
        <li v-for="(item,i) in list" :key="i">{{item}}</li>
      </ul>
    </div>
    <script src="https://unpkg.com/vue@next"></script>

    <script>
      const { reactive, toRefs, watchEffect, watch, computed, ref } = Vue;
      Vue.createApp({
        setup() {
          const state = reactive({
            count: 1,
            newCount: null,
          });

          watchEffect(() => {
            // setTimeout(() => {
            //   state.newCount = state.count * 2;
            // }, 1000);
            state.newCount = state.count * 2;
          });

          watch(
            () => state.count,
            (count, prev) => {
              console.log(count, prev);
            }
          );

          const num = ref(0);

          watch(num, (nm, prev) => console.log(nm, prev, "ref watch"));

          const interval = setInterval(() => {
            if (state.count >= 10) {
              clearInterval(interval);
            }
            state.count++;
            num.value++;
          }, 2000);

          // 测试demo
          const msg = reactive({
            list: ["java", "php"],
            val: "",
            valDesc: computed(() => `输入的值是:${msg.val}`),
          });

          function addCourse() {
            msg.list.push(msg.val);
          }

          return {
            ...toRefs(state),
            num,
            ...toRefs(msg),
            addCourse,
          };
        },
      }).mount("#app");
    </script>
  </body>
</html>

4.provide,inject

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <div id="app">
        <p>useCounter:{{count}}</p>
        <cp></cp>
        <p><button @click="setCount(number)">设置值</button></p>
        
    </div>
    <script src="https://unpkg.com/vue@next"></script>

    <script type="text/x-template" id="comp">
        <input v-model="val" />
    </script>

    <script type="module">
      import { useCounter } from "./hook.js";
      const { reactive, ref, toRefs, provide, inject } = Vue;

      const Comp= {
          template: "#comp",
          setup(){
              const val= inject("num");
              return {
                val
              };
          }
      }
  
      Vue.createApp({
        components:{
            cp: Comp
        },  
        setup() {
          const [count, setCount] = useCounter();

          const number= ref(10);
          provide("num",number);

          return {
            count,
            setCount,
            number
          };
        },
      }).mount("#app");
    </script>
  </body>
</html>

5.directive

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <div id="app">
      <input v-focus v-model="val" />
      <p><button @click="changeShow">改变权限</button></p>
      <p v-permission="show">用户名</p>
    </div>
    <script src="./vue.js"></script>

    <script>
      const { createApp, reactive, toRefs } = Vue;

      const app = createApp({
        setup() {
          const state = reactive({
            val: "",
            show: true,
          });
          function changeShow() {
            state.show = !state.show;
            console.log(state.show);
          }
          return {
            ...toRefs(state),
            changeShow,
          };
        },
        directives: {
          permission(el, binding) {
            if (!binding.value) {
              el.style.display = "none";
            } else {
              el.style.display = "block";
            }
          },
        },
      });

      app.directive("focus", {
        mounted(el) {
          el.focus();
        },
      });

      app.mount("#app");
    </script>
  </body>
</html>

6.teleport

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <style>
      .md {
        width: 400px;
        height: 200px;
        position: fixed;
        top: 50%;
        left: 50%;
        box-shadow: 0 0 3px 3px rgba(0, 0, 0, 0.1);
        transform: translate(-50%, -50%);
      }
    </style>
  </head>
  <body>
    <div id="app">
      <button @click="changeShow">打开/关闭</button>
      <modal v-model:visible="show"></modal>
      <div id="md"></div>
    </div>
    <script src="./vue.js"></script>

    <script type="text/x-template" id="modal">
      <teleport :to="dom" v-if="dom">
          <div class="md" v-show="vib">
              <p>这是个弹框</p>
              <slot></slot>
              <button @click="$emit('update:visible',false)">关闭</button>
          </div>
      </teleport>
    </script>

    <script>
      const { reactive, ref, computed, onMounted } = Vue;

      const Modal = {
        template: "#modal",
        props: ["visible"],
        emits: ["update:visible"],
        setup(props) {
          const vib = computed(() => props.visible);
          let dom = ref(null);
          onMounted(() => {
            dom.value = document.getElementById("md");
          });
          return {
            vib,
            dom,
          };
        },
      };

      Vue.createApp({
        components: {
          Modal,
        },
        setup() {
          const show = ref(false);

          function changeShow() {
            show.value = !show.value;
            console.log(show.value);
          }

          return {
            show,
            changeShow,
          };
        },
      }).mount("#app");
    </script>
  </body>
</html>

7.h render渲染

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <div id="app">
      <input v-model="appVal" />
      <button @click="getVal">获取值</button>
      <x-head :level="2" :list="[1,2,3,4,85]">测试标题</x-head>
      <l-input v-model="lVal"></l-input>
    </div>
    <script src="./vue.js"></script>
    <script type="text/x-template" id="input">
      <p>这是个输入组件</p>
      <input :value="modelValue" @input="$emit('update:modelValue',$event.target.value)"  />
    </script>
    <script>
      const { createApp, h, ref } = Vue;

      const AInput = {
        template: "#input",
        props: ["modelValue"],
        emits: ["update:modelValue"],
      };

      createApp({
        setup() {
          const appVal = ref("");
          const lVal = ref("1");
          function getVal() {
            console.log(appVal.value, "appVal");
            console.log(lVal.value, "lVal");
          }
          return {
            appVal,
            getVal,
            lVal,
          };
        },
      })
        .component("x-head", {
          props: {
            level: {
              type: Number,
              required: true,
            },
            list: Array,
          },
          render() {
            if (this.list && this.list.length > 0) {
              const children = this.list.map((item) =>
                h(
                  "li",
                  {
                    // onClick: {
                    //   handler: () => {
                    //     console.log("click", item);
                    //   },
                    //   once: true,
                    //   capture: true,
                    // },
                    title: item,
                    onDblclick: () => console.log("db", item),
                  },
                  item
                )
              );
              return h("ul", children);
            } else {
              return h(`h${this.level}`, this.$slots.default());
            }
          },
        })
        .component("l-input", {
          props: ["modelValue"],
          emits: ["update:modelValue"],
          render() {
            return h(AInput, {
              modelValue: this.modelValue,
              "onUpdate:modelValue": (val) =>
                this.$emit("update:modelValue", val),
            });
          },
        })
        .mount("#app");
    </script>
  </body>
</html>

8. 插件

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <style>
      .mes {
        width: 400px;
        height: 200px;
        position: fixed;
        top: 50%;
        left: 50%;
        box-shadow: 0 0 3px 3px rgba(0, 0, 0, 0.1);
        transform: translate(-50%, -50%);
      }
    </style>
  </head>
  <body>
    <div id="app">
      <button @click="showMsg">打开消息</button>
    </div>
    <script src="./vue.js"></script>

    <script type="text/x-template" id="mes">
      <div class="mes">
          {{msg}}
      </div>
    </script>
    <script>
      const { createApp, render, h } = Vue;

      const app = createApp({
        methods: {
          showMsg() {
            this.$message({ msg: "测试" });
          },
        },
      });

      const MessagePlugin = {
        install() {
          const Message = {
            template: "#mes",
            props: {
              duration: {
                type: Number,
                default: 2000,
              },
              msg: String,
            },
            mounted() {
              setTimeout(() => {
                app.config.globalProperties.$message(null);
              }, this.duration);
            },
          };

          const container = document.createElement("div");
          document.body.appendChild(container);

          app.config.globalProperties.$message = (props) => {
            if (props) {
              render(h(Message, { msg: props.msg }), container);
            } else {
              render(null, container);
            }
          };
        },
      };

      app.use(MessagePlugin);

      app.mount("#app");
    </script>
  </body>
</html>

9.hook.js

const { onMounted, onUnmounted, ref } = Vue;

export function useCounter() {
    
  const count = ref(0);
  let timer;

  onMounted(() => {
    timer = setInterval(() => {
      count.value++;
    }, 1000);
  });

  function setCount(val) {
    count.value = val;
  }

  onUnmounted(() => {
    clearInterval(timer);
  });

  return [count, setCount];
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值