Vue3

1、数据双向绑定

<body>
    <div id="app">
        <h1>{{msg}}</h1>
    </div>


    <script src="https://unpkg.com/vue@next"></script>
    <script>

        /* 使用vue对象创建vue实例
            mount("#app")挂载
        */
        Vue.createApp({
            data() {
                return {
                    msg: "数据双向绑定!"
                }
            }
        }).mount("#app");

    </script>
</body>

2、常用例子

1. 如何操作文本

<body>
    <div id="app">
        <!-- 指令:vue提供的一些特殊属性v-开头 -->
        <h1 v-text="msg"></h1>
    </div>
    <script src="https://unpkg.com/vue@next"></script>
    <script>
        Vue.createApp({
            // 选项api(option api)
            data() {
                return {
                    msg: "数据双向绑定!-绑定文本"
                }
            }
        }).mount("#app");

    </script>
</body>

2. 如何操作html的属性

<body>
    <div id="app">
        <!-- 指令:vue提供的一些特殊属性v-开头 -->
        <h1 v-text="msg" v-bind:title="tit"></h1>
    </div>

    <script src="https://unpkg.com/vue@next"></script>
    <script>
        Vue.createApp({
            // 选项api(option api)
            data() {
                return {
                    msg: "数据双向绑定!-绑定文本",
                    tit: "操作属性!title"
                }
            }
        }).mount("#app");

    </script>
</body>

3. 如何绑定事件

<body>
    <div id="app">
        <!-- 指令:vue提供的一些特殊属性v-开头 -->
        <h1 v-text="msg" v-bind:title="tit" v-on:click="showData"></h1>
    </div>

    <script src="https://unpkg.com/vue@next"></script>
    <script>
        Vue.createApp({
            // 选项api(option api)
            data() {
                return {
                    msg: "数据双向绑定!-绑定文本",
                    tit: "操作属性!title"
                }
            },
            methods: {
                showData() {
                    alert("绑定事件!")
                }
            }
        }).mount("#app");

4. 计数器练习

<body>
    <div id="app">
        <button v-on:click="decrease">-</button>
        <span>{{number}}</span>
        <button v-on:click="increase">+</button>
    </div>

    <script src="https://unpkg.com/vue@next"></script>
    <script>
        Vue.createApp({
            // 选项api(option api)
            data() {
                return {
                    number: 0
                }
            },
            methods: {
                decrease() {
                  if(this.number>0){
                     this.number--;
                  }
                },
                increase() {
                    this.number++;
                }
            }
        }).mount("#app");

    </script>
</body>

5. 渲染列表图片切换

<body>
    <div id="app">
        <img :src="src" alt="">
        <button @click="changePic(0)">1</button>
        <button @click="changePic(1)">2</button>
        <button @click="changePic(2)">3</button>
        /*<button v-for="item,index in list" @click="changePic(index)">{{index+1}}</button>*/


    </div>

    <script src="https://unpkg.com/vue@next"></script>
    <script>
        Vue.createApp({
            // 选项api(option api)
            data() {
                return {
                    src: "1.jpg",
                    list: [
                        "1.jpg",
                        "2.jpg",
                        "3.jpg",
                    ]
                }
            },
            methods: {
                changePic(i) {
                    this.src = this.list[i];
                }
            }
        }).mount("#app");

    </script>
</body>

6. 渲染列表

<body>
    <div id="app">
        <ul>
            <li v-for="item in list">{{item}}</li>
        </ul>
    </div>

    <script src="https://unpkg.com/vue@next"></script>
    <script>
        Vue.createApp({
            // 选项api(option api)
            data() {
                return {
                    list: [
                        "香蕉",
                        "苹果",
                        "梨子"
                    ]
                }
            },
            methods: {

            }
        }).mount("#app");

    </script>
</body>

7. 添加数据

<body>
    <div id="app">
        <button @click="insert">添加品种</button>
        <ul>
            <li v-for="item in list">{{item}}</li>
        </ul>
    </div>

    <script src="https://unpkg.com/vue@next"></script>
    <script>
        Vue.createApp({
            // 选项api(option api)
            data() {
                return {
                    list: [
                        "香蕉",
                        "苹果",
                        "梨子"
                    ]
                }
            },
            methods: {
                insert() {
                    this.list.push("猕猴桃")
                }

            }
        }).mount("#app");

    </script>
</body>

3、表单提交双向数据绑定

<body>
    <div id="app">
        <!-- 阻止默认提交行为@submit.prevent -->
        <form @submit.prevent="post">
            <input type="text">
            <button>提交表单</button>
        </form>
    </div>

    <script src="https://unpkg.com/vue@next"></script>
    <script>
        Vue.createApp({
            // 选项api(option api)
            data() {
                return {

                }
            },
            methods: {
                post() {
                    console.log("表单提交");
                }

            }
        }).mount("#app");

    </script>
</body>

双向绑定

<body>
    <div id="app">
        <!-- 阻止默认提交行为@submit.prevent -->
        <form @submit.prevent="post">
            <input type="text" v-model="msg">
            <button>提交表单</button>
        </form>
        <h1>{{msg}}</h1>
    </div>

    <script src="https://unpkg.com/vue@next"></script>
    <script>
        Vue.createApp({
            // 选项api(option api)
            data() {
                return {
                    msg: "我是表单里的数据"

                }
            },
            methods: {

            }
        }).mount("#app");

    </script>
</body>

输出
v-model.number="msg"输出数值
v-model.lazy="msg" 失去焦点的时候再绑定
v-model.trim="msg" 去掉空格

<body>
    <div id="app">
        <!-- 阻止默认提交行为@submit.prevent -->
        <form @submit.prevent="post">
       <!--v-model.number="msg"输出数值 -->
            <input type="text" v-model="msg">
            <button>提交表单</button>
        </form>
        <h1>{{msg}}</h1>
    </div>

    <script src="https://unpkg.com/vue@next"></script>
    <script>
        Vue.createApp({
            // 选项api(option api)
            data() {
                return {
                    msg: "我是表单里的数据"

                }
            },
            methods: {
                post() {
                    console.log(this.msg);
                }

            }
        }).mount("#app");

    </script>
</body>

简单购物车

<body>
    <div id="app">
        <h1>水果列表</h1>
        <form @submit.prevent="insert">
            <span>品种:</span><input type="text" v-model="name">
            <span>价格:</span><input type="text" v-model.number="price">
            <button>添加</button>
        </form>
        <ul>
            <li v-for="item,index in list">
                名称:{{item.name}}
                单价:{{item.price}}
                <button @click="decrease(index)">-</button>
                数量:{{item.count}}
                <button @click="increase(index)">+</button>

            </li>
        </ul>
        <h3>总计:{{totalPrice}}</h3>
    </div>

    <script src="https://unpkg.com/vue@next"></script>
    <script>
        Vue.createApp({
            // 选项api(option api)
            data() {
                return {
                    name: "",
                    price: 0,
                    list: [
                    ]
                }
            },
            computed: {
                totalPrice() {
                    let sum = 0;
                    this.list.forEach(v => {
                        sum += (v.price) * (v.count)
                    })
                    return sum;
                }
            },
            methods: {
                insert() {
                    this.list.push({
                        name: this.name,
                        price: this.price,
                        count: 1
                    })
                },
                decrease(i) {
                    this.list[i].count--;
                    if (this.list[i].count <= 0 && confirm("是否删除")) {
                        this.list.splice(i, 1);
                    }
                },
                increase(i) {
                    this.list[i].count++
                }
            }
        }).mount("#app");

    </script>
</body>

4、组件化开发

定义:
app.component("组件名",{
template:组件模板
});
使用:<组件名></组件名>

<body>
    <div id="app">
        <hello></hello>
    </div>

    <script src="https://unpkg.com/vue@next"></script>
    <script>
        const app = Vue.createApp({
            // 选项api(option api)
            data() {
                return {}
            }
        });
        app.component("hello", {
            data() {
                return {
                    msg: "我是组件hello"
                }
            },
            template: `
                <h1>{{msg}}</h1>
            `
        });
        app.mount("#app");

    </script>
</body>

组件可以嵌套:组件模板里面放子组件标签

app.component("hello", {
            data() {
                return {
                    msg: "我是组件hello"
                }
            },
            template: `
                <h1>{{msg}}</h1>
                <child></child>
            `
        });
app.component("child", {
            data() {
                return {
                    msg: "我是组件hello的子组件"
                }
            },
            template: `
                <h1>{{msg}}</h1>
            `
        });

1.根组件:

const app=Vue.createApp({});
//根组件
const rootComponent=app.mount("#app");

2.全局组件与局部组件

使用component方法注册的组件叫全局组件
可以使用components属性实现局部组件

<body>
    <div id="app">
        <my-hello></my-hello>
    </div>

    <script src="https://unpkg.com/vue@next"></script>
    <script>
        const myHello = {
            template: `
            <h1>局部组件</h1>`
        }

        const app = Vue.createApp({
            components: {
                "myHello": myHello
            }
        })

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

在局部组件1中使用局部组件2要在局部组件1中注册组件2

3.组件的生命周期

1.创建 create
没有data(),method() 在js中创建虚拟dom
2.挂载 mount
有了data(),method()挂载到html上
3.详细

  1. beforeCreate()
    没有数据和方法
  2. created()
    有数据有方法,没有dom
  3. beforeMount()
    没有dom,有数据
  4. mounted()
    能够拿到标签,有dom,有数据
  5. 用在刷新页面的时候,自动加载
<body>
    <div id="app">
        <h1>{{msg}}</h1>
    </div>

    <script src="https://unpkg.com/vue@next"></script>
    <script>

        const app = Vue.createApp({
            data() {
                return {
                    list: ["你好", "亲爱的用户", "很高兴见到你"],
                    msg: ""
                }
            },
            created() {
                this.showData();
            },
            methods: {
                showData() {
                    let i = 0;
                    let t = setInterval(() => {
                        this.msg = this.list[i];
                        i++;
                        if (i === 3) {
                            clearInterval(t);
                        }
                    }, 500)
                }
            }
        })

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

5、自定义指令

刷新页面自动获取焦点

<body>
    <div id="app">
        <input ref="inp" type="text">
        <button>搜索</button>
    </div>

    <script src="https://unpkg.com/vue@next"></script>
    <script>

        const app = Vue.createApp({
            data() {

            },
            mounted() {
                this.$refs.inp.focus();
            }

        })

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

自定义指令

<body>
    <div id="app">
        <input v-focus type="text">
        <button>搜索</button>
    </div>

    <script src="https://unpkg.com/vue@next"></script>
    <script>

        const app = Vue.createApp({

        })
        app.directive("focus", {
            mounted(el) {
                el.focus()
            }
        })
        app.mount("#app")
    </script>
</body>

6、路由

npm i --save vue-router@4

1. 配置俩页面

<template>
  <router-link to="/home">首页</router-link>
  |
  <router-link to="/blog">博客</router-link>
  <router-view></router-view>
</template>

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

2. 设置路由

import { createRouter } from "vue-router";

const router = createRouter({
    
});

export default router;
3. main.js中引入路由

import { createApp } from 'vue'
import App from './App.vue'
import './index.css'

import router from "./router.js"

const app = createApp(App)
app.use(router)
app.mount('#app')

4. 配置路由

import { createRouter, createWebHashHistory } from "vue-router";
import Home from "./components/Home.vue";
import Blog from "./components/Blog.vue";


const router = createRouter({
    history: createWebHashHistory(),
    routes: [
        {
            path: "/home",
            component: Home
        },
        {
            path: "/blog",
            component: Blog
        },
    ]
});

export default router;

7、路由传参(动态路由)

<template>
  <router-view></router-view>
</template>

<script>
export default {
  name: "App",
};
</script>
 <router-link :to="'/blog/' + item.id">{{ item.title }}</router-link>
<template>
  <h1>列表</h1>
  <ul>
    <li v-for="item in blogList">
      <router-link :to="'/blog/' + item.id">{{ item.title }}</router-link>
    </li>
  </ul>
</template>

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

  data() {
    return {
      blogList: [
        { id: 1, title: "测试文章1" },
        { id: 2, title: "测试文章2" },
        { id: 3, title: "测试文章3" },
        { id: 4, title: "测试文章4" },
        { id: 5, title: "测试文章5" },
      ],
    };
  },
};
</script>
 <h1>博客详情:{{ $route.params.id }}</h1>
<template>
  <h1>博客详情:{{ $route.params.id }}</h1>
</template>

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

  data() {
    return {};
  },
};
</script>
 	{
            path: "/blog/:id",
            component: Blog
        },
import { createRouter, createWebHashHistory } from "vue-router";
import List from "./components/List.vue";
import Blog from "./components/Blog.vue";


const router = createRouter({
    history: createWebHashHistory(),
    routes: [
        {
            path: "/",
            component: List
        },
        {
            path: "/blog/:id",
            component: Blog
        },
    ]
});

export default router;
<template>
  <h1>博客详情:{{ $route.params.id }}</h1>
  <p>
    {{ blogContent }}
  </p>
</template>

<script>
export default {
  data() {
    return {
      blogContent: "",
    };
  },
  created() {
    let id = this.$route.params.id;
    this.getBlogDataById(id);
  },
  methods: {
    getBlogDataById(id) {
      switch (id) {
        case "1":
          this.blogContent = "第一篇测试";
          break;
        case "2":
          this.blogContent = "第二篇测试";
          break;
        case "3":
          this.blogContent = "第三篇测试";
          break;
        case "4":
          this.blogContent = "第四篇测试";
          break;
        case "5":
          this.blogContent = "第五篇测试";
          break;
      }
    },
  },
};
</script>

8、实现登录

<template>
  <h1>登录</h1>
  <form @submit.prevent="login">
    <div>
      <label>用户名:</label>
      <input type="text" v-model="username" />
    </div>
    <div>
      <label>密码:</label>
      <input type="password" v-model="password" />
    </div>
    <button>登录</button>
  </form>
</template>

<script>
export default {
  data() {
    return {
      username: "",
      password: "",
    };
  },
  methods: {
    login() {
      if (this.username === "admin" && this.password === "123456") {
        this.$router.push("/list");
      } else {
        alert("用户名或密码错误!");
      }
    },
  },
};
</script>

9、验证登录状态

localStorage.setItem("token", "token1111");

<template>
 <h1>登录</h1>
 <form @submit.prevent="login">
   <div>
     <label>用户名:</label>
     <input type="text" v-model="username" />
   </div>
   <div>
     <label>密码:</label>
     <input type="password" v-model="password" />
   </div>
   <button>登录</button>
 </form>
</template>

<script>
export default {
 data() {
   return {
     username: "",
     password: "",
   };
 },
 methods: {
   login() {
     if (this.username === "admin" && this.password === "123456") {
       this.$router.push("/list");
       localStorage.setItem("token", "token1111");
     } else {
       alert("用户名和密码错误!");
     }
   },
 },
};
</script>

created() {
console.log(localStorage.getItem("name"));
},

<template>
<h1>列表</h1>
<ul>
  <li v-for="item in blogList">
    <router-link :to="'/blog/' + item.id">{{ item.title }}</router-link>
  </li>
</ul>
</template>

<script>
export default {
created() {
  console.log(localStorage.getItem("name"));
},
data() {
  return {
    blogList: [
      { id: 1, title: "测试文章1" },
      { id: 2, title: "测试文章2" },
      { id: 3, title: "测试文章3" },
      { id: 4, title: "测试文章4" },
      { id: 5, title: "测试文章5" },
    ],
  };
},
};
</script>
// 导航守卫:路由拦截、路由守卫
router.beforeEach((to, from, next) => {
    // 验证token,只有存在token的时候才能跳转到内容页
    let token = localStorage.getItem("token");
    if (token || to.path === "/login") {
        next();
    } else {
        next("/login");
    }
})
import { createRouter, createWebHashHistory } from "vue-router";
import List from "./components/List.vue";
import Blog from "./components/Blog.vue";
import Login from "./components/Login.vue";



const router = createRouter({
    history: createWebHashHistory(),
    routes: [
        {
            path: "/login",
            component: Login
        },
        {
            path: "/list",
            component: List
        },
        {
            path: "/blog/:id",
            component: Blog
        },
    ]
});
// 导航守卫:路由拦截、路由守卫
router.beforeEach((to, from, next) => {
    // 验证token,只有存在token的时候才能跳转到内容页
    let token = localStorage.getItem("token");
    if (token || to.path === "/login") {
        next();
    } else {
        next("/login");
    }
})
export default router;

10、组合api-响应式变量

所有功能写在set up(){}
npm init vite-app demovue3

<template>
  <h1>{{ title }}</h1>
  <button @click="sayHi">按钮</button>
</template>

<script>
export default {
  setup() {
    let title = "组合api";

    function sayHi() {
      alert("组合api,暴露什么就用什么");
    }
    return {
      title,
      sayHi,
    };
  },
};
</script>

1. 响应式:ref把字符串变为响应式变量

<template>
  <h1>{{ title }}</h1>
  <button @click="sayHi">按钮</button>
</template>

<script>
// 解构一个ref
import { ref } from "vue";
export default {
  setup() {
    // 把字符串变为响应式变量
    let title = ref("组合api");

    function sayHi() {
      title.value = "hello 我是响应式变量";
    }
    return {
      title,
      sayHi,
    };
  },
};
</script>
  1. reactive将对象变成响应式对象
<template>
  <h1>{{ title }}</h1>
  <p>{{ student.name }}</p>
</template>

<script>
// 解构一个ref
// reactive将对象变成响应式对象
import { reactive, ref } from "vue";
export default {
  setup() {
    // 把字符串变为响应式变量
    let title = ref("组合api");
    const student = { name: "小明", age: 2 };

    return {
      // 绑定到页面
      title,
      student,
    };
  },
};
</script>
<template>
  <h1>{{ title }}</h1>
  <button @click="sayHi">按钮</button>
  <p>{{ student.name }}</p>
</template>

<script>
// 解构一个ref
// reactive将对象变成响应式对象
import { reactive, ref } from "vue";
export default {
  setup() {
    // 把字符串变为响应式变量
    let title = ref("组合api");
    const student = reactive({ name: "小明", age: 2 });
    function sayHi() {
      student.name = "我是小红";
    }
    return {
      title,
      student,
      sayHi,
    };
  },
};
</script>

3.生命周期

beforeCreate——>use setup()
created——>use setup()
解构:
beforeMount——>onBeforeMount
mounted——>onBeforeUpdate
beforeUnmount——>onBeforeUnmount
unmounted——>onUnmounted

<template>
  <h1>{{ title }}</h1>
</template>

<script>
import { onMounted, ref } from "vue";
export default {
  setup() {
    const list = ["你好", "亲爱的用户", "很高兴遇见你"];
    const title = ref("");

    onMounted(() => {
      let i = 0;
      let t = setInterval(() => {
        title.value = list[i];
        i++;
        if (i === 3) {
          clearInterval(t);
        }
      }, 500);
    });
    return {
      title,
    };
  },
};
</script>

11、计算属性

<template>
  <h1>{{ number }}</h1>
</template>

<script>
import { computed } from "vue";
export default {
  setup() {
    const number = computed(() => {
      return 100;
    });
    return {
      number,
    };
  },
};
</script>

<template>
  <h1>苹果 2元一斤</h1>
  <button @click="decrease">-</button>
  <span>{{ number }}</span>
  <button @click="increase">+</button>
  <h2>总计:{{ totalPrice }}</h2>
</template>

<script>
import { computed, ref } from "vue";
export default {
  setup() {
    const number = ref(0);
    function increase() {
      number.value++;
    }
    function decrease() {
      number.value--;
    }
    const totalPrice = computed(() => {
      return number.value * 2;
    });
    return {
      number,
      increase,
      decrease,
      totalPrice,
    };
  },
};
</script>
posted @ 2022-05-26 20:56  flyall  阅读(39)  评论(0)    收藏  举报