学习vue

vue

1、开发环境准备

安装node https://nodejs.org/en/

安装Vue工具

Vue CLi 安装命令:npm install -g @vue/cli

安装之后查看

vue --version

image-20221028160730511

vue 官网:https://cn.vuejs.org/

2、创建项目

vue create 项目名

注意:项目名字不能大写

image-20221028161135154

选择

image-20221028161216545

根据自己的需要选择

image-20221028161320975

默认即可

image-20221028161401172

输入n即可

image-20221028161500899

根据提示运行项目

image-20221028161622151

启动成功

image-20221028161721011

image-20221028161738061

3、模板语法

<template>
  <div>
    <h3>学习模板语法</h3>
    <p>{{message}}</p>
  </div>
</template>

<script>
export default {
  name: 'HelloWorld',
  data() {
    return {
      message:"测试"
    }
  }
}
</script>
1、v-html  解析html标签
2、v-bind  响应式地绑定
3、v-if、v-else  根据值的真假移除或添加元素
4、v-show   根据值的真假显示或隐藏元素

4、列表渲染

v-for

<template>
  <div>
    <h3>列表渲染</h3>
    <ul>
      <li v-for="(item,index) in names">{{ item.name }}------>{{ index }}</li>
    </ul>
  </div>
</template>

<script>
export default {
  name: 'HelloWorld',
  data() {
    return {
      names: [
        {id: 1, name: "小明"},
        {id: 2, name: "老大"},
        {id: 3, name: "老二"}
      ]
    }
  }
}
</script>

<style scoped>
ul {
  list-style: none;
}
</style>

image-20221028221126686

注意

<li v-for="(item,index) in names" :key="item.id">{{ item.name }}------>{{ index }}</li>
:key="item.id" 在数组元素改变时,会只重新渲染改变的数据,其它没变的不会重新渲染
减少性能的消耗

5、事件处理

@click或v-on:click

<template>
  <div>
    <h3>事件处理</h3>
    <button v-on:click="dianJi">点击</button>
    <h3>{{num}}</h3>
  </div>
</template>

<script>
export default {
  name: 'HelloWorld',
  data() {
    return {
      num: 0
    }
  },
  methods: {
    dianJi() {
      this.num += 1;
    }
  }
}
</script>

<style scoped>
ul {
  list-style: none;
}
</style>

image-20221028222405803

6、双向数据绑定

v-model

<template>
  <div>
    <h3>双向数据绑定</h3>
    <input type="text" v-model="username">
    <h3>{{username}}</h3>
  </div>
</template>

<script>
export default {
  name: 'HelloWorld',
  data() {
    return {
      username: ""
    }
  }
}
</script>

<style scoped>
ul {
  list-style: none;
}
</style>

image-20221028222739981

1、v-model.lazy  加上后输入数据回车或失去焦点才进行同步
2、v-model.trim 去除输入的空格

7、单文件组件

1、组件内容

<template>
  <div>
    <h3>单文件组件</h3>
  </div>
</template>

<script>
export default { //导出
  name: "MyComponents",
  data() {
    return {}
  }
}
</script>
//scoped 添加这属性 组件内设置的样式只会作用在这个组件
<style scoped>
h3 {
  color: red;
}
</style>

2、加载组件

1、引入组件  import myComponents from "@/components/MyComponents";
2、挂载组件components: {myComponents}
3、显示组件<my-components/>

image-20221028224131539

8、组件交互

props 父组件向子组件传值

 1、在父组件定义好值
  data() {
    return {
      title: "我是一个标题",
      age: 100
    }
  }
2、在显示组件上引用
<my-components :oneHiz="title" :age="age"/> 
3、最后在子组件上使用
export default {
  name: "MyComponents",
  props:{
    oneHiz:{ //需要定义类型
      type:String,
      default:""
    },
    age:{
      type:Number,
      default:0
    }
  }
}

9、自定义事件组件交互

现在子组件定义传递的值和事件

<template>
  <div>
    <h3>自定义组件传递数据</h3>
    <button @click="sendFather">发送</button>
  </div>
</template>

<script>
export default {
  name: "MyComponents",
  data() {
    return {
      msg: "我是MyComponents数据"
    }
  },
  methods: {
    sendFather() {
      //参数1: 字符串
      //参数2: 传递的数据
      this.$emit("onEvent", this.msg)
    }
  }
}
</script>

<style scoped>
h3 {
  color: red;
}
</style>

父组件接受值

<template>
  <div>
    <img alt="Vue logo" src="./assets/logo.png">
    <my-components @onEvent="getData"/>
  </div>
</template>

<script>

import myComponents from "@/components/MyComponents";

export default {
  name: 'App',
  components: {
    myComponents
  },
  methods: {
    getData(data) {
      console.log(data)
    }
  }
}
</script>

<style>
div {
  width: 400px;
  height: 400px;
  text-align: center;
  margin: 0 auto;
}
</style>

作用:子组件向父组件传递值

时间:2022-10-28 晚上

10、组件的生命周期

创建时: beforeCreate、Created
渲染时: beforeMount、mounted
更新时: beforeUpdate、updated
卸载时: beforeUnmount、unmounted
<template>
  <div>
    <h3>组件生命周期</h3>
    <p>{{ msg }}</p>
    <button @click="msg='数据'">点击</button>
  </div>
</template>

<script>
export default {
  name: "MyComponents",
  data() {
    return {
      msg: ""
    }
  },
  beforeCreate() {
    console.log("beforeCreate:组件创建之前!")
  },
  created() {
    console.log("created:组件创建完成!")
  },
  beforeMount() {
    console.log("beforeCreate:组件渲染之前!")
  },
  mounted() {
    //网络请求通常放在这里
    console.log("created:组件渲染完成!")
  },
  beforeUpdate() {
    console.log("beforeCreate:组件更新之前!")
  },
  updated() {
    console.log("created:组件更新完成!")
  },
  beforeUnmount() {
    //把消耗性能的处理都干掉 例如: 定时器
    console.log("beforeCreate:组件卸载之前!")
  },
  unmounted() {
    console.log("created:组件卸载完成!")
  }
}
</script>

<style scoped>
h3 {
  color: red;
}
</style>

image-20221029104441220

image-20221029104458983

11、vue引入第三方

image-20221029104840609

swiper官网:https://swiper.com.cn/

安装: cnpm install --save swiper

指定版本安装 : cnpm install --save swiper@8.1.6

卸载依赖包: cnpm uninstall swiper --save

官方文档:https://swiperjs.com/vue

12、Axios 网络请求

官网:https://www.axios-http.cn/

安装依赖包:cnpm install --save axios

1、局部引入

<template>
  <div>
    <h3>{{ Details.title }}</h3>
    <p>{{ Details.content }}</p>
  </div>
</template>

<script>
import axios from 'axios'
import querystring from "querystring"

export default {
  name: "MyComponents",
  data() {
    return {
      Details: [{
        title: "",
        content: ""
      }]
    }
  },
  mounted() {
    axios.get("http://iwenwiki.com/api/blueberrypai/getChengpinDetails.php").then(res => {
      this.Details = res.data.chengpinDetails[0]
    });
    axios.post("http://iwenwiki.com/api/blueberrypai/login.php", querystring.stringify({
      user_id: "iwen@qq.com",
      password: "iwen123",
      verification_code: "crfvw"
    })).then(res=>{
      console.log(res.data)
    });
  }
}
</script>

<style scoped>
h3 {
  color: red;
}
</style>

image-20221029133727169

2、全局引入

image-20221029134039320

引入

image-20221029134256120

13、网络请求的封装

image-20221029222532889

request.js

import axios from "axios"
import * as querystring from "querystring";


const errorHandle = (status, info) => {
    switch (status) {
        case 400:
            console.log("语义有误");
            break;
        case 401:
            console.log("服务器认证失败");
            break;
        case 403:
            console.log("服务器拒绝访问");
            break;
        case 404:
            console.log("地址错误");
            break;
        case 500:
            console.log("服务器遇到意外");
            break;
        case 502:
            console.log("服务器无响应");
            break;
        default:
            console.log(info)
            break;
    }
}


const instance = axios.create({
    //网络请求的公共配置
    timeout: 5000
})
//拦截器
//发送数据之前
instance.interceptors.request.use(config => {
    if (config.method === "post") {
        config.data = querystring.stringify(config.data)
    }
    //config包含网络请求的所有信息
    return config;
}, error => {
    return Promise.reject(error)
})
//获取数据之前
instance.interceptors.response.use(
    response => {
        return response.status === 200 ? Promise.resolve(response) : Promise.reject(response)
    }, error => {
        const {response} = error;
        //错误的处理
        errorHandle(response.status, response.info)
    }
)

export default instance;

path.js

const base = {
    baseUrL: "http://iwenwiki.com",
    chengpin: "/api/blueberrypai/getChengpinDetails.php"
}

export default base

index.js

import axios from "../utils/request";
import path from "./path"

const api = {
    //成品详情地址
    getChengpin() {
        return axios.get(path.baseUrL + path.chengpin)
    }
}


export default api

调用接口

<template>
  <div>

  </div>
</template>

<script>
import api from "../api/index"

export default {
  name: "MyComponents",
  data() {
    return {}
  },
  mounted() {
    api.getChengpin().then(res => {
      console.log(res.data)
    })
  }
}
</script>

<style scoped>
h3 {
  color: red;
}
</style>

时间:2022-10-29 晚上

14、网络请求跨域解决方案

目前主流的跨域解决方案有两种

1、后台解决cors

2、前台解决proxy

devServer:{
    proxy:{
      '/api':{
        target:'http://iwenwiki.com',//跨域的url
        changeOrigin: true
      }
    }
  }

image-20221030105540217

image-20221030105645717

15、vue引入路由

1、安装路由:cnpm install --save vue-router

2、在src创建router文件夹,在创建index.js文件

index.js

import {createRouter, createWebHashHistory} from "vue-router";
import homeView from "@/views/HomeView";
import aboutView from "@/views/AboutView";

//配置信息中需要的页面相关配置
const routes = [
    {
        path: '/',
        component: homeView
    },
    {
        path: '/about',
        component: aboutView
    }
]

const router = createRouter({
    history: createWebHashHistory(),
    routes
})

export default router;

image-20221030125302700

image-20221030125517633

createWebHashHistory和createWebHistory区别

createWebHashHistory

image-20221030125754978

createWebHistory

image-20221030125719021

1、createWebHashHistory
   原理:a标签锚点链接
2、createWebHistory
  此种方式需要后台配合做重定向,否则会出现404问题
原理: H5 pushState()

16、路由传递参数

1、现在路由链接指定:网易新闻

image-20221030140027596

2、在index.js 文件

{
        path: '/details/:name',
        name: 'details',
        component: () => import('../views/news/NewsDetailsView')
}

image-20221030140222166

image-20221030140417370

17、路由嵌套

首先我创建了如下几个文件

image-20221030143114446

路由设置

{
        path: '/books',
        name: 'books',
        //重定向
        redirect: '/books/info',
        component: () => import('../views/BookView'),
        children: [
            {//二级导航的路径不加/
                path: 'us',
                component: () => import('../views/books/BookUsView')
            },
            {
                path: 'info',
                component: () => import('../views/books/BookInfoView')
            }
        ]
    }

BookView.vue

<template>
  <div>
    <router-link to="/books/info">提示信息</router-link>|
    <router-link to="/books/us">一起看书</router-link>
  </div>
  <router-view/>
</template>

<script>
export default {
  name: "BookView"
}
</script>

<style scoped>

</style>

18、Vue状态管理(Vuex)

1、安装Vuex :npm install --save vuex

2、配置Vuex文件

import {createStore} from "vuex";

//vuex核心作用就是帮助我们管理组件之间的状态
export default createStore({
    //所有的状态都放在这里(数据)
    state:{
        counter:0
    }
})

3、在主文件中引入Vuex

import store from "@/store";
app.use(store)

4、在组件中读取状态

//读取方式
第一种读取方式:  {{ $store.state.counter }}
//第二种读取方式
import {mapState} from "vuex";


computed: {
    ...mapState(["counter"])
}

//如何直接引入
{{ counter }}

image-20221030170645513

19、Vuex状态管理核心

常用核心包括

State Getter Mutation Action

1、Getter

import {createStore} from "vuex";

//vuex核心作用就是帮助我们管理组件之间的状态
export default createStore({
    //所有的状态都放在这里(数据)
    state: {
        counter: 10
    },
    getters: {
        getCounter(state) {
            return state.counter > 0 ? state.counter : "counter数据异常";
        }
    }
})
//直接调用
<p>{{ $store.getters.getCounter }}</p>

//或者这样调用
 <p>{{ getCounter }}</p>

<script>
import {mapGetters} from "vuex";

export default {
  name: 'App',
  computed: {
    ...mapGetters(["getCounter"])
  }
}
</script>

2、Mutation

import {createStore} from "vuex";

//vuex核心作用就是帮助我们管理组件之间的状态
export default createStore({
    //所有的状态都放在这里(数据)
    state: {
        counter: 10
    },
    getters: {
        getCounter(state) {
            return state.counter > 0 ? state.counter : "counter数据异常";
        }
    },
    mutations: {//事件
        addCounter(state, num) {
            state.counter += num
        }
    }
})

调用

 <button @click="addClickHandle">点击</button>

//第一种调用
<script>
import {mapGetters, mapMutations} from "vuex";

export default {
  name: 'App',
  computed: {
    ...mapGetters(["getCounter"])
  },
  methods:{
    addClickHandle(){
      //固定调用方式
      this.$store.commit("addCounter",15)
    }
  }
}
</script>
 <button @click="addClickHandle">点击</button>

//第二种调用方式
<script>
import {mapGetters, mapMutations} from "vuex";

export default {
  name: 'App',
  computed: {
    ...mapGetters(["getCounter"])
  },
  methods:{
    ...mapMutations(["addCounter"]),
    addClickHandle(){
      this.addCounter(20)
    }
  }
}
</script>

3、Action

概述:Action类似于Mutation,不同在于

1、Action提交的是mutation,而不是直接变更状态

2、Action可以包含任意异步操作

import {createStore} from "vuex";
import axios from "axios";

//vuex核心作用就是帮助我们管理组件之间的状态
export default createStore({
    //所有的状态都放在这里(数据)
    state: {
        counter: 10
    },
    getters: {
        getCounter(state) {
            return state.counter > 0 ? state.counter : "counter数据异常";
        }
    },
    mutations: {
        addCounter(state, num) {
            state.counter += num
        }
    },
    //为异步操作所准备的
    actions: {
        asyncAddCounter({commit}) {
            axios.get("http://iwenwiki.com/api/generator/list.php").then(res => {
                //使用方式
                commit("addCounter",res.data[0])
            })
        }
    }
})

调用

<button @click="addAsyncClickHandle">异步增加</button>
//第一种调用
<script>
import {mapGetters, mapMutations} from "vuex";

export default {
  name: 'App',
  computed: {
    ...mapGetters(["getCounter"])
  },
  methods: {
    ...mapMutations(["addCounter"]),
    addClickHandle() {
      this.addCounter(20)
    },
    addAsyncClickHandle() {
    this.$store.dispatch("asyncAddCounter")
    }
  }
}
</script>
<button @click="addAsyncClickHandle">异步增加</button>

//第二种调用
<script>
import {mapGetters, mapMutations, mapActions} from "vuex";

export default {
  name: 'App',
  computed: {
    ...mapGetters(["getCounter"])
  },
  methods: {
    ...mapMutations(["addCounter"]),
    ...mapActions(["asyncAddCounter"]),
    addClickHandle() {
      //固定调用方式 
      this.addCounter(20)
    },
    addAsyncClickHandle() {
      this.asyncAddCounter()
    }
  }
}
</script>

20、Vue3新特性1

ref 或者 reactive

1、在2.x中通过组件data的方法定义一些当前组件的数据

data(){
    return{
      name:'hu',
      list:[]
    }
}

2、在3.x中通过ref或者reactive创建响应式对象

<template>
  <div>
    <h3>关于页面</h3>
    <h4>{{ message }}</h4>
    <ul>
      <li v-for="(item,index) in names.list" :key="index">{{ item }}</li>
    </ul>
    <button @click="clickHandle">点击</button>
  </div>
</template>

<script>
import {ref, reactive} from "vue";

export default {
  name: "AboutView",
  //组合式API
  setup() {
    //ref
    const message = ref("我是消息")
    //reactive
    const names = reactive({
      list: ["老大", "老二", "老三"]
    })

    function clickHandle() {
      console.log("点击了")
    }

    return {
      message,
      names,
      clickHandle
    }
  }
}
</script>

<style scoped>

</style>

时间:2022-10-30 晚上

21、Vue3新特性2

在setup中使用生命周期函数

<script>
import {onMounted} from "vue";

export default {
  name: "AboutView",
  //组合式API
  setup() {
    //可以声明多个生命周期函数,在2.x版本每个生命周期函数只能声明一个
    onMounted(() => {
      console.log("onMounted生命周期1")
    })
    onMounted(() => {
      console.log("onMounted生命周期2")
    })
  }
}
</script>

Provide 和inject 可以实现嵌套组件间的数据传递

注:这两个函数只能在setup中使用

1、父组件中使用Provide()向下传递数据

2、子组件使用inject() 获取数据

3、传递数据由上至下

//父组件
<script>
  import {provide} from "vue";
  export default { 
     setup(){
        provide("msg","我是消息")
    }
  }
</script>
//子组件
<script>
import {inject} from "vue";
  const message = inject("msg")
    return {
      message
    }    
</script>

fragment

1、在2.x版本组件只能有一个根节点

2、载3.x版本组件根节点个数没有限制

3、但推荐只能有一个根节点

<template>
   //多个根节点,但实际还是推荐使用一个根节点
  <div>
  </div>
  <p></p>
</template>

22、Vue3加载Element-plus

安装:cnpm install element-plus --save

1、完整引入 会把整个文件都打包

//导入
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'

app.use(ElementPlus)

然后直接使用即可

<template>
  <el-row class="mb-4">
    <el-button>Default</el-button>
    <el-button type="primary">Primary</el-button>
    <el-button type="success">Success</el-button>
    <el-button type="info">Info</el-button>
    <el-button type="warning">Warning</el-button>
    <el-button type="danger">Danger</el-button>
  </el-row>
</template>

2、按需导入

1、首先安装两款插件

cnpm install -D unplugin-vue-components unplugin-auto-import

安装后配置vue.config.js 即可使用

const {defineConfig} = require('@vue/cli-service')
const AutoImport = require('unplugin-auto-import/webpack')
const Components = require('unplugin-vue-components/webpack')
const {ElementPlusResolver} = require('unplugin-vue-components/resolvers')


module.exports = defineConfig({
    transpileDependencies: true,
    configureWebpack: {
        plugins: [
            AutoImport({
                resolvers: [ElementPlusResolver()]
            }),
            Components({
                resolvers: [ElementPlusResolver()]
            })
        ]
    }
})    

23、Vue3加载Element-plus的字体图标

1、安装字体图标:cnpm install @element-plus/icons-vue

2、全局注册

//在src下创建plugins文件夹里再创建icons.js
import * as components from "@element-plus/icons-vue"

export default {
    install: (app) => {
        for (const key in components) {
            const componentConfig = components[key]
            app.component(componentConfig.name, componentConfig)
        }
    }
};

3、在main.js引入

import elementIcon from "./plugins/icons"

app.use(elementIcon)

最后引入即可

<el-icon :size="100" color="red"><Unlock /></el-icon>

时间:2022-10-31 午休

posted @ 2022-10-28 23:10  有何和不可  阅读(78)  评论(0)    收藏  举报