学习的内容过程

Vue2

vue是什么

渐进式 JavaScript 框架

特点

易用,灵活,高效

{{}} 插值表达式 data底层Object.definePropertygettersetter进行设置 一次只能对一个所以要遍历递归

给元素添加动态的内容

可以处理四则运算 三元运算

可以执行js代码(只能是js表达式)

vue2原理Object.defineProperty vue3原理Proxy

v-for

列表渲染

注意:v-for 需要和key一起使用,这个key要是唯一的 根据key进行底层的diff算法比对 这个key=》在vue底层用来辨别是不是同一个元素 如果是复用,如果不是重新创建

v-on

为解决这一问题,Vue 为 v-on 提供了事件修饰符。修饰符是用 . 表示的指令后缀,包含以下这些:

  • .stop 阻止事件冒泡

  • .prevent 阻止默认行为

  • .self

  • .capture

  • .once 只触发执行 一次

  • .passive

 <button data-id='100' @click="adds">点</button>
    自定义属性
adds(event){
   console.log(event.target.dataset.id);
    console.log(event);
}

指令总结

必须需要记住的: v-bind ,{{}},v-on,v-for,v-if,v-show,v-model 双向数据绑定,v-html 数据是HTML标签不会作为vue模板进行编译(根据应用的场景进行理解)

记住:v-text 更新元素文本标签,v-once 只渲染一次{{}}, v-cloak 不会显示直到编译结束

computed

康pu替d

计算属性 一定要有return具有缓存机制 在页面中调用n次只要依赖的数据没有改变只会执行一次 不能写异步return是同步涉及微任务宏任务 计算属性还可以写成对象形式需要修改数据的时候写成对象形式里面有get和set get获取处理的数据 set设置数据

watch

四种写法可以写异步 immediate:true //立即执行 默认为false deep:true //默认为false深度监听 写成字符串函数形式就可以就深度数据的准确监听 页面渲染的时候传递过来的是数值需要用watch监听不然会出现结构出现数据没出现

<div class="list-item" v-for="(item,index) in newList " :key="index" >
data(){
       return{
          newList:[]
       }
   },  
watch:{
       hotData(newVal,oldVal){//直接的数据是hotData数组wacth进行监听拿到新值进行for循环
               this.newList = newVal
       }
   },

filters

数据格式不是我们想要的 过滤器分全局注册和局部注册和计算属性很像不能写异步 vue3快不用了

生命周期

baforeCerate 比佛克瑞t vue实例创建之前 初始化vue实例上的属性 watch computed data methdes

created vue实例创建之后 vue实例上的属性 watch computed data methdes 创建完毕 发网络请求

beforeMount 比佛莽t vue实例挂载到浏览器之前

mounted 莽t诶d vue实例挂载到浏览器上 浏览器上有dom结构

beforeUpdate 比佛up得t 页面更新之前

update 页面更新完毕

beforeDestroy 比佛迪丝qu 页面摧毁前

destroyed 迪丝qu 页面摧毁后

vueCli

(1)安装

npm install -g @vue/cli
​

(2)检测vueCli版本

vue --version

(3)通过vueCli传教项目

vue create 项目名称

(4)自定义模块 =》通过键盘上下箭头(进行却换)=》在同回车键确定(表示选中)

(5)选择我们需要的依赖babel=>将es6的语法=》es5 需要通过上下箭头却换 =》在通过空格选择于不选中=》 按下回车

(6)请选择vue的版本 =》vue2

(7)是否需要将bable放到独立的文件中?是的

(8)是否需要将上面操作保存起来,不用

(9) cd当前的项目

vue项目目录分析

node_modules=》依赖包

public=》公共的文件

src=>核心代码

assets=》公共方法

components=》组件

app.vue =>根组件

main.js 入口文件=》这个文件中代码只要项目运行就会执行

babel.config.js=>babel 文件

jsconfig.js =>js文件

package-lock.json =》项目依赖包的版本

package.json=》当前项目的配置文件

vue.config=》webpack配置文件

(1)启动项目

npm run serve  =>http://localhost:8080/

分析思路?

执行机制

(1)先执行main.js 中的代码

//(1)引入vue
//(2)引入组件 根组件=>vue.component()
//(3)创建vue实例
//(4)组将组件内容编译完成之后渲染到指定位置

分析.vue文件?

template :写内容=》 html
​
script=>js=》当前组件的vue实例
​
style 样式

快速创建 .vue文件 在vscode 中安装 vetur

组件

创建局部组件

(1)在component 创建组件 康pu闷丝

(2)在app.vue组件中进行引入 注册 使用

注册全局组件

1.在mian.js中定义 vue.components('组件名字'组件内容) 文件抽离出去export暴露出去 全局使用

组件传值

<HelloWorldVue :items="age" @getFa="getFas"></HelloWorldVue>
 props:{
    // items:{
    //   type:Number
    // }
    items:Number
},
​
<button @click="add">+</button>
methods:{
    add(){
      console.log('触发了子组件');
      this.$emit('getFa',4000)//自定义子组件给父组件传递数据
    }
}
methods:{
    getFas(val){
        console.log(val);
    }
  }

兄弟传值

export let eventBus = new Vue() //main.js
import {eventBus} from '@/main.js'
methods:{
        change(){
            eventBus.$emit('getBro',1000)
        }
    }
​
 mounted(){
        eventBus.$on('getBro',(data)=>{
                console.log(data);
        })
    }

父组件给子组件传递数据

方法:(1)在父组件中通过定义属性 (2)在子组件中通过props进行接收

子组件给父组件数据

方法:通过自定义事件 $emit('事件',数据) 在父组件中 通过v-on (@) 来进行接收,

注意这事件处理的方法,他会自动执行

兄弟数据传递

通过中心事件

 //处理 中心事件  new Vue() =>Vue 在node_modules里面=>注意在项目中 要使用node_modules里面的包
import Vue from 'vue'
export  let eventBus = new Vue()

4其他的方法

(1)本地存放数据

(2)provide,inject

(3) vuex

作用相对于全局变量,在父组件中提供数据,在子组件中获取数据(封装UI组件库)

使用步骤:在最外层组件中提供数据 在需要数据的组件中获取数据

export default {
  // 声明全局变量
  provide:{
   obj:{name:'张三',age:20},
   nums:100
    }
  }
 //(2)在子组件中获取这个数据
    inject:['obj','nums'],//值是数组

存储

JSON.stringify()将对象变成字符串 JSON.parse()将字符串变成对象

组件插槽

为什么要使用插槽 作用:封装组件 可以进行复用,但是 有时候封装的组件,是根据使用的时候,来确定布局,和里面的内容 封装ui组件库

匿名插槽

就是slot 没有name属性 作用:接收组件写的全部内容

app.vue //组件的内容
<ChildrenItem>
      <!-- 内容 -->
      <template>
        <div>西瓜</div>
        <div>桃子</div>
        <div>香蕉</div>
      </template>
    </ChildrenItem>
  <div>
         <!--内容布局不是一开始就写死了  -->
         <!-- slot:作用:接收组件使用的时候,组件传递是内容
          -->
          <!-- 匿名插槽 -->
          <slot ></slot>
     </div>

具名插槽

作用:分发内容的时候可以一一对应

(1)确定分发的内容(名称)
 <ChildrenItem>
      <!-- template -->
      <template slot="top">
        <div class="topStyle">
        </div>
      </template>
      <template slot="content">
        <div>
        </div>
      </template>
      <template slot="foot">
        <div>foot</div>
      </template>
    </ChildrenItem>
(2) <slot 需要有name属性> =》通过这个name 属性实现一一对应
     <!-- 具名插槽 -->
    <slot name="top"></slot>
    <slot name="content"></slot>
    <slot name="foot"></slot>

作用域插槽

作用:就是分发的内容数据是子组件传递过来的

(1)在组件中通过自定义属性在slot上传递数据
    <slot  name="header"  :list='list'></slot>
<slot  name="content"  :list='lists'></slot>
(2)在分发内容中通过v-slot:名称=”slotProps“ v-slot:自定义可以写具名插槽然后合并
 <template v-slot:content="slotProps">
        <!-- 2获取子组件中数据 -->
        <div class="topStyle">
          <!-- 数据(动态数据=》子组件): -->
          <div v-for="(item, index) in slotProps.list" :key="index">
            {{ item }}
          </div>
        </div>
      </template>
      

Vue.use()

作用:就是我们自己写的方法和vue项目产生关联

Vue.use(插件) 
1 执行里面的方法
2 如果这个方法或者对象,里面有一个属性 ,是install,会执行install这个给方法
3 这个方法,有参数,第一参数就是当前项目vue实例
function autoComponent(){
    cosole.log('我是vue.use里的参数')
}
autoComponent.install=function(_Vue){
    cosole.log('install',_Vue)
}

vue全家桶

vue-router vuex 不是vue实例自带的本质是插件

路由

npm install vue-router@3.5.1

$router每个带vue的文件实例上都有这个方法 $route当前路由信息

什么是路由

根据浏览器上的路由地址=》对应匹配展示我们的组件

前端路由有那几种方式?

方式1:history=>历史的路由模式 他是没有#

方式2:hash=>路由模式 hash=> #/

路由两个全局组件

1router-link

作用:相对于a标签

属性:to 和a标签中href =》路径

2router-view

作用:根据当前路由信息匹配组件=》进行展示

3:链式编程进行跳转

路由跳转分为3种方式

push:跳转路径的时候,是向浏览器历史栈中追加路由信息,他可以进行回退

replace:替换浏览器历史栈中的路径,他不能进行回退

go: 指定回退到浏览器历史栈中的那一个路径 用法:go(负数回退) go(正式前进)

4:路由传递参数

1)路由参数可以看到=》 query 体现:路由地址上可以看到参数

this.$router.push({path:'/detail',query:{product_id:1000}})

2)字符串模模板进行拼接

this.$router.push(`/detail?id=${id}`)

3)params方式 体现:不能看到参数

this.$router.push({name:'Detail',params:{id}})

5获取到路由参数

注意:获取路由参数=》来到另外一个页面=》走我们的生命周期钩子函数=》

created,mounted

1)query

(1)获取到当前路由信息=》$route (2)结合我的生命周期

   mounted(){
       //获取到当前的路由信息=》产品详情页面
       //获取到路由参数=>$route.
       console.log(this.$route.query.id,'获取到params 传递是参数');
   }

2)parmas

(1)获取到当前路由信息=》$route (2)结合我的生命周期

mounted(){
       //获取到当前的路由信息=》产品详情页面
       //获取到路由参数=>$route.
       console.log(this.$route.params.id,'获取到params 传递是参数');
   }

6 嵌套路由

什么是嵌套路由? 就是在页面级组件中在展示页面级的组件

 你是谁的嵌套路由,就在路由信息中添加一个children:[]
   {
    path:'/',
    name:'Content',
    component:Content,
    // 嵌套的路由=》发现音乐,播客
    children:[
      {
        // 注意:嵌套路由的路径=》 /findMusic
        path:'findMusic',
        name:'FindMusic',
        component:FindMusic
      },
      {
        // 注意:嵌套路由的路径=》 /findMusic
        path:'play',
        name:'Play',
        component:Play
      }
    ]
  }

7路由重定向

什么是路由重定向? 可以指向我们想要去的的路径

{
    path:'/',
    name:'Content',
    component:Content,
    redirect:'/findMusic', // 作用;当前浏览器路由地址 /=》/findMusic 瑞得赖克T

八别名(不重要)

/a 的别名是 /b,意味着,当用户访问 /b 时,URL 会保持为 /b,但是路由匹配则为 /a,就像用户访问 /a 一样。

const router = new VueRouter({
  routes: [
    { path: '/a', component: A, alias: '/b' }
  ]
})

九路由守卫

(1)是什么? 他可以时时检测路由地址的变化 在工作中你常用的路由守卫有那些 我在工作中经常用的是前置路由守卫经常在项目中用来做一些权限验证

1.1前置路由守卫

router.beforeEach((to,from,next)=>{
    to:去到那个页面
    from:从那个页面过来
    next()//继续向下执行=》 执行路由匹配
})

总结路由守卫

(1)核心就是前置路由守卫的使用=>权限校验

(2)后置路由守卫

( 3)独享路由守卫 beforeEnter 比佛恩得

(4)组件的内的路由守卫 beforeRouterEnter

十:路由配置信息

meta: 路由元信息 语法:meta:{属性自定义}

const router = new VueRouter({
  routes: [
    {
      path: '/foo',
      component: Foo,
      children: [
        {
          path: 'bar',
          component: Bar,
          // a meta field
          meta: { requiresAuth: true }
        }
      ]
    }
  ]
})

十一 路由懒加载

作用:展示到这个组件的时候=》才加载这个组建的代码=》提高项目首次加载的速度

 component:()=>import('组件的路由')

分析:

搭建了一个项目,首次在浏览器上显示=》 只需要显示首页(不需要显示的组件,在首次渲染项目的时候,不需要进行加载)

ref

获取到元素的真实dom ref="refs" this.$refs 任意方法直接自动调用真实dom 打印出来是个对象consolse.log(this.$refs) this.$refs.refss拿到真实dom

axios

为什么不用ajxs:

axios底层就是ajxs和promise底层进行封装的

  • 从浏览器中创建 XMLHttpRequests http请求

  • 从 node.js 创建 http 请求

  • 支持 Promise API

  • 拦截请求和响应

  • 转换请求数据和响应数据

  • 取消请求

  • 自动转换 JSON 数据

  • 客户端支持防御 XSRF

get请求传递参数需要用params()

创建axios实例对象

axios.create({})

VueX

npm install vuex@3.6.2

vuex是干什么的: 全局状态管理

为什么要用vuex: 因为在工作中数据传递有一个数据在多个组件中进行使用这个时候就可以用vuex

用data代理后赋值生命周期只会触发一次 写成了data代理方式

state getters get丝 actions aix询丝

state

state存放数据=》相对于vue实例中的data

为什么state是响应式的 因为他和vue的data是一样的他的底层就是将他里面所有的属性通过vue中的data进行代理了一遍

作用:vuex存放数据=>并且这个数据是响应式=》他实现的原理就是和vue中的data一样

在vue项目中获取state的属性

   方式1;通过属性 =》this.$store.state.属性
   方式2:辅助函数=》mapState=>就是将state中所有的属性代理成计算属性
        使用: computed:{ ...mapState(['state想要用的属性'])}

getters

相对于vue中的计算属性=》特点:具有缓存机制

state的数据不是我们想要的通过getters改变

 getters:{
     自定义属性:function(第一参数就是state){
         return 逻辑处理
     }
 }

作用: 就是vuex中state存放的数据,不是我们直接想要的,我们可以通过getters属性进行处理

本质:就是vue中的计算属性

在项目中获取getters的属性

方式1;通过属性 =》this.$store.getters.属性
   方式2:辅助函数=》mapGetters=>就是将getters中所有的属性代理成计算属性
        使用: computed:{ ...mapGetters(['getters想要用的属性'])}

mutations

作用:定义属性用来修改state中的数据(并且式唯一的方法)

注意在vuex我们在state中定义的数据只能在mutations中定义方法来修改

mutations:{
    属性:方法(state,触发这个方法传递的数据)
}

触发state中定义的数据通过commit('mutations中的属性',传递是数据)

作用:是vuex唯一修改state中数据的方式 ,缺点:只能写同步方法

在项目中的使用:

方式1;通过属性 =》this.$store.commit('属性',数据)
   方式2:辅助函数=》mapMutations=>就是将mutation中所有的属性代理成方法
        使用: methods:{ ...mapMutations(['mutation想要用的属性'])}

actions

作用:异步修改数据

本质:就是获取到异步的数据,在通过commit触发mutations中定义方法

actions

1、用于通过提交mutation改变数据

2、会默认将自身封装为一个Promise

3、可以包含任意的异步操作

语法:: AychangeAge(第一个参数是store,同dispatch 调用传递参数)

   AychangeAge(store){
              //异步处理
              setTimeout(() => {
                  //获取到数据
                  let val = 200
                  //修改state中的数据=》通过commit触发 mutations中定义的方法
                  store.commit('changeAge',val)
              }, 2000);
        }

在vue组件中触发actions中定义的方法=》dispatch('actions中的方法',需要传递的参数)

 ayadd(){
             //如果触发actions中定义方法
             //方法:dispatch('actions中定义方法',传递的数据)
             this.$store.dispatch('AychangeAge',400)
    }

作用:异步修改数据=>本质:获取到异步的数据,在通过commit触发mutations中定义的方法,来修改数据

在项目中的使用

方式1;通过属性 =》this.$store.dispatch('属性',数据)
   方式2:辅助函数=》mapActions=>就是将actions中所有的属性代理成方法
        使用: methods:{ ...mapActions(['mutations想要用的属性']}

modules

我们在工作中项目很大,在vuex中的state存放的数据很多,可能有上百个,

这个上百个数据,这些数据是可以进行区分,购物车,我的模块,各自保存

作用:模块化处理=>让我们的项目,集中处理对应的模块

注意:用来模块化一定要添加一个命名空间(namespaced:ture)

keep-alive

(1)需要知道我们写的项目,那些页面是首次进来更新数据,后面不用更新数据,

那些页面是每次都要更新数据

用法:

  <keep-alive >
          <!-- 嵌套的路由=》视频和音乐组件 
        
           使用keep-alive 包裹路由占位符,这个路由占位符,匹配的组件
            他只会在首次渲染的的时候,触发我们的常规 的8生命周期,在次在浏览器上渲染的这个组件的
            时候不在触发,=》保存了这个组件
        -->
          <router-view></router-view>
        </keep-alive>

注意在我们工作中:缓存了这个给页面,但是这个页面中有一些数据也是时时更新,

那么在浏览器上显示缓存组件的时候也要自动触发一个方法,自动执行和生命周期一样的

activated:相对于生命周期的created ei克t舞t
​
deactivated://隐藏了=》相对于生命周期 摧毁

问题:怎么找到我们项目中那些是需要缓存的组件,那些不是

解决方法:

 1 在路由文件中router/index.js 给我们需要缓存的组件添加一个自定义属性
 meta:{keepAlive:true}
​
2在有使用路由占位符的地方进行判断=》条件渲染
    注意:这个判断要放到路由占位符上
      <div class="content">
      <!-- !selectItem :视频: -->
 
        <keep-alive  >
          <!-- 嵌套的路由=》视频和音乐组件 
        
           使用keep-alive 包裹路由占位符,这个路由占位符,匹配的组件
            他只会在首次渲染的的时候,触发我们的常规 的8生命周期,在次在浏览器上渲染的这个组件的
            时候不在触发,=》保存了这个组件
        -->
       
          <router-view v-if="iskeepAlive"></router-view>
        </keep-alive>
        <router-view v-if="!iskeepAlive"></router-view>
    </div>
3需要通过监听路由信息 进行处理
 '$route':{
      handler(newVal){
          console.log(newVal);
          if(newVal.meta.keepAlive){ //这个组件需要缓存
              this.iskeepAlive = true
          }else{
              this.iskeepAlive = false
          } 
      },
      immediate: true, //第一次也执行
    }
​

工作中怎么做keep-alive 儿赖无 缓存的 我会自己封装 给路由中添加一个自定义标签组件meta设置为true 然后用wacth进行路由的深度监听通过if拿到路由信息进行判断这个组件是否需要缓存 可以设置立即执行监听

Vue3

day1

一创建vue3项目=》vuecli

1:分析项目目录=》和vue2一样的

2:分析src/main.js这个文件

import { createApp } from 'vue'  //就是vue2 vue实例
import App from './App.vue'  //根组件
import router from './router'  //路由
import store from './store'  //vuex
​
  let app = createApp(App)   //创建app实例=》vue实例 =》vue2  new Vue({})
  app.use(store) // 注册插件  Vue.use()
  app.use(router).mount('#app')
​

二:初始vue3 写法

单文件组件

1 setup 作用

<script setup> // {}
​
// (1) 如果你在 script 添加了setup => 他就是组件实例=》向当于vue2 exportt default {}
//  (2) script 中的代码 还会自动给执行=》相对于vue2的 created=>执行了初始化
   console.log('自动给执行 created');
</script>

2 vue3中的数据类型

/二:数据的处理之数据类型
 //(1)动态数据=》需要在页面进行处理=》响应式的数据  (2)死的数据(不用改变的数据)
let num = 100 //死的数据,不可以改变的数据

三响应式api

(1)ref

作用:将基本的数据类型=》代理成响应式的数据=》底层使用 Object.defineProperty()

语法:ref(初始值) =》返回的是一个对象 ,对象中有一个value,这个value就是我们的值

   let num = ref(0)

(2)reactive

作用;代理 引用组件类型 =》返回代理对象

语法: reactive(数据),=》返回值是一个对象 =>Proxy

let obj = reactive({arrs:['1','2','3','4']}) // 理解reactive 代理的数据就是vue2的data

总结这个两个可以处理vue2中的data 了

(3)readonly (面试问题)

作用;处理的数据只能获取不能进行修改,注意需要代理 响应式是的数据 reactive ref

语法:readonly(处理响应式数据)=>返回一个对象

  import {readonly,reactive,ref} from 'vue'
   //readonly
   //作用;处理的数据只能获取不能进行修改,注意需要代理 响应式是的数据 reactive ref
   //语法:readonly(处理响应式数据)=>返回一个对象
//    let obj = reactive({nums:0})
 let obj = ref(0)
    let readonlyObj = readonly( obj) //Proxy:{nums:0}
    console.log(readonlyObj);
    setTimeout(() => {
        readonlyObj.value =20 //修改数据
    }, 1000);

(4)shallowReactive (面试问题)

作用:代理第一次属性为响应式的,其他层次都是不是响应式的

核心 我用shallowReactive 我有一些数据 是动态的,一些数据是写死的,动态的数据复制

//作用:代理第一次属性为响应式的,其他层次都是不是响应式的
 //核心 我用shallowReactive 我有一些数据 是动态的,一些数据是写死的,动态的数据复制
const state = shallowReactive({
  foo: 1, //动态的我们进行复制
  nested: { //写死的,你需要复制吗?
    bar: 2,
  },
});
​
​
onMounted(()=>{
    //宏任务
    console.log('获取到后台的数据=》Mounted');
    // state.foo++
      state.nested.bar++;     
})

(5)shallowReadonly (面试问题)

//作用: 第一层是只读的

const state = shallowReadonly({
  foo: 1, //第一层数据
  nested: {
    bar: 2,
  },
});
console.log(state);
onMounted(() => {
  //vue mounted
  state.foo = 4;
})

总结:就是处理 vue2中的data属性

工作中使用 三个 ref, reactive,toRefs

四:vue3中的方法处理=>vue2 methods

在vue3单文件组件中

(1)我们在teamplate中方法的调用该,在vue3单文件组件中直接写道 script 第一次

<script setup>
    function change(){
    console.log('触发');
     state.nested.bar++;     
}
    
    </script> =》{}

五:watch 和computed

computed

作用:和vue2一样的,将这个数据处理成我们想要的,具有缓存机制 ,必须是同步的方法

用法:1 computed(处理函数,中一定要有retrun)

let age = ref(20)
//处理我哥哥的业务
  let getBro = computed(()=>{
         return age.value +10
     })

用法二:computed(写一个对象具有get,和set 属性)

//用法二: computed(写一个对象具有get,和set 属性)
let getBro = computed({
    get:()=>{ //获取值的时候触发
          return  age.value +39
    },
    set:(val)=>{ //设置值的时候触发 ,val 就是我们设置的值
        console.log(val);
    }
})
console.log(getBro);
getBro.value = 60

watch

作用:和vue2一样的,用来监听数据(响应式组件),可以写异步方法

语法1:监听单一数据源

//watch
//监听单一数据源
//语法1: watch(监听的数据(ref =》值),处理方法)
//语法2:watch(监听的数据(reactive =》值),处理方法)
watch(age ,(newVal,oldVal)=>{
         console.log(newVal);
         //写业务逻辑
})
//注意如果使用watch 监听的是ref,reactive中的动态属性,需要在sh写方法
watch(()=>state.num,(newVal,oldVal)=>{
console.log(newVal);
})
setTimeout(() => {
    // age.value = 40
    state.num = 60
}, 1000);

语法2:监听多个数据源

//多个数据源
//语法:watch([监听数据1,监听的数据2],处理方法)
watch([age,num],([foo, bar], [prevFoo, prevBar])=>{
    //[foo, bar] 第一参数都是新值
    //[prevFoo, prevBar] 第二个参数说旧的值
   console.log(foo,bar);
    console.log(prevFoo,prevBar);
})
setTimeout(() => {
     age.value =100
     num.value =600
}, 1000);

vue3+后台架构

一:搭建项目(技术栈)

vue3+vue-router+vuex+axios+less+element-ui

二:请求的封装

1:添加公共的属性和设置请求拦截和响应拦截

2:实现页面和请求一一对应

三: element ui安装

安装

npm install element-plus --save

按需导入

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

vue.config.js

const AutoImport = require('unplugin-auto-import/webpack')
const Components = require('unplugin-vue-components/webpack')
const { ElementPlusResolver } = require('unplugin-vue-components/resolvers')
const { defineConfig } = require('@vue/cli-service')
module.exports = defineConfig({
  transpileDependencies: true,
  configureWebpack:{
    plugins: [
      AutoImport({
        resolvers: [ElementPlusResolver()],
      }),
      Components({
        resolvers: [ElementPlusResolver()],
      }),
    ],
  }
​
})
​

直接在项目中使用element

四;安装less

npm install less less-loader

四:后台管理系统的登录授权

1:输入用户名称和密码=》点击登录=>成功=》内部页面

1)输入用户名称和密码发送请求

2)成功登录=》(1)返回token(唯一标识)

(2)根据用户名称和密码 动态生成路由

实现:

(1)写登录页面

1)核心修改elementui组件库的样式,添加我们想要的功能,就是我们vue中的事件,和动态绑定属性

 <el-form
        ref="formRef"
        :model="numberValidateForm"
        label-width="60px"
        hide-required-asterisk
        class="demo-ruleForm"
      >
        <el-form-item
          label="用户"
          prop="name"
          :rules="[
            { required: true, message: 'Please enter the correct user name' },
            { type: 'number', message: 'age must be a number' },
          ]"
        >
          <el-input
            v-model.number="numberValidateForm.name"
            type="text"
            autocomplete="off"
          />
        </el-form-item>
        <el-form-item
          label="密码"
          prop="password"
          :rules="[
            {
              required: true,
              message: 'Please enter the correct user password',
            },
            { type: 'number', message: 'password must be a number' },
          ]"
        >
          <el-input
            v-model.number="numberValidateForm.password"
            type="text"
            autocomplete="off"
             :show-password="isPassword"
            :suffix-icon="isShow"
          />
          <!--  -->
          <div class="clickIcon" @click="clickIcon"> </div>
        </el-form-item>
        <div>
          <el-button type="primary" @click="submitForm(formRef)"
            >Submit</el-button
          >
          <el-button @click="resetForm(formRef)">Reset</el-button>
        </div>
      </el-form>

<template>
  <!-- 
写页面
​
​
 -->
  <div class="login">
    <div class="from">
      <el-form
        ref="formRef"
        :model="numberValidateForm"
        label-width="60px"
        hide-required-asterisk
        class="demo-ruleForm"
      >
        <el-form-item
          label="用户"
          prop="name"
          :rules="[
            { required: true, message: 'Please enter the correct user name' },
          ]"
        >
          <el-input
            v-model.number="numberValidateForm.name"
            type="text"
            autocomplete="off"
          />
        </el-form-item>
        <el-form-item
          label="密码"
          prop="password"
          :rules="[
            {
              required: true,
              message: 'Please enter the correct user password',
            },
            { type: 'number', message: 'password must be a number' },
          ]"
        >
          <el-input
            v-model.number="numberValidateForm.password"
            type="text"
            autocomplete="off"
            :show-password="isPassword"
            :suffix-icon="isShow"
          />
          <!-- 
​
          1:刚开始的时候 密码是看不到的
​
           -->
          <div v-if="isPassword" class="clickIcon" @click="clickIcon(true)"></div>
          <div v-else class="clickIcon" @click="clickIcon(false)"></div>
        </el-form-item>
        <div>
          <el-button type="primary" @click="submitForm(formRef)"
            >Submit</el-button
          >
          <el-button @click="resetForm(formRef)">Reset</el-button>
        </div>
      </el-form>
    </div>
  </div>
</template>
​
<script setup>
// {}
import { reactive, ref } from "vue"; //响应式api
import { Search, Calendar } from "@element-plus/icons-vue"; //获取到 icon
const numberValidateForm = reactive({  //定义响应式api
  name: "",
  password: "",
});
let isPassword = ref(true); //表示密码隐藏
let isShow = ref("");
const submitForm = () => {};
const resetForm = () => {};
​
//密码显示处理方法
function clickIcon(val) {
  if (val) { //现在是密码隐藏的状态=》密码看的见
    isShow.value = Calendar;
    isPassword.value = false;
  }else{ //现在是密码 看的见=》密码隐藏的状态
       isShow.value = '';
    isPassword.value = true;
    console.log(555555);
  }
}
</script>
​
<style scoped lang="less">
//处理element -ui 样式
//(1)在浏览器中找到这个样式
// deep
/deep/.el-form-item {
  height: 50px;
  line-height: 50px;
  border: 1px solid rgba(255, 255, 255, 0.1);
  background: rgba(0, 0, 0, 0.1);
  border-radius: 5px;
  color: #454545;
  padding-right: 20px;
}
/deep/.el-input__wrapper {
  background: rgba(0, 0, 0, 0.1);
  border: 0px;
  box-shadow: 0 0 0 0px;
}
/deep/.el-input__inner {
  background: rgba(0, 0, 0, 0.1);
  border: 0px;
  -webkit-appearance: none;
  border-radius: 0px;
  padding: 12px 5px 12px 15px;
  color: #fff;
  height: 47px;
  caret-color: #fff;
}
​
/deep/.el-form-item__label {
  // display: inline-flex;
  // justify-content: flex-end;
  // align-items: flex-start;
  // flex: 0 0 auto;
  font-size: var(--el-form-label-font-size);
  color: var(--el-text-color-regular);
  height: 32px;
  line-height: 32px;
  // padding: 0 12px 0 0;
  box-sizing: border-box;
  margin-top: 9px;
  color: red;
}
​
.login {
  height: 100%;
  background-color: #2d3a4b;
  .from {
    width: 50%;
    height: 400px;
    border-radius: 30px;
    position: relative;
    width: 520px;
    max-width: 100%;
    padding: 160px 35px 0;
    margin: 0 auto;
    overflow: hidden;
    .clickIcon {
      // background:blue;
      position: absolute;
      right: 10px;
      width: 30px;
      height: 30px;
    }
  }
}
</style>

vue3 路由跳转在项目中的使用

(1)引入

import {useRouter} from 'vue-router'

(2)获取到路由实例方法

let router = useRouter()
​

(3)实现跳转

  router.push('/home')

注意:抽离的方法,有路由跳转,需要在setup中先获取到router 实例,在到我们抽离的文件中使用

setup中的代码抽离

/**
 *  核心 
 *   (1)这个业务,功能的相关数据 (全部在这个文件)
 *   (2) 注意 这个模块 中数据在template  有使用那些=》处理到 setup的第一层
 *   (3)需要注意route  =》 写一个方法
 * 
 *    注意:setup=>
 * 
 * ***/ 

element-ui 在项目中修改

  //处理element -ui 样式
//(1)在浏览器中找到这个样式
// deep

前端处理路由权限(内部页面和外部页面)

1实现方法:路由守卫

2我们需要知道那些页面级的组件 是内部页面

beforeEach.js

//引入
import router from './index'
​
//
router.beforeEach((to,from,next)=>{
    console.log(to);
    if(to.meta.token){ //1如果我们去的是内部页面,需要登录
          if(sessionStorage.getItem('token')){ // 是登录了
                   next()
          }else{ //没有登录
            next({path:'/'})
          }
    }else{ // 去的是外部页面
        next()
    }
    
})

根据权限动态的生成路由

我这个后台管理系统:超级管理员 ,管理员, 用户

共有的:

(1)我们都有公共页面: Dashboard ,chart

各自:

超级管理员: tabel

管理员:theme

用户看的到的就是共有的

实现的方法

(1)将所有的页面级的组件在views中创建

(2)创建路由表,所有权限的路由信息全部创建完毕

(3)根权限动态生成侧边栏导航,

1)侧边栏导航的数据=》后台给的数据

动态生成侧边栏导航

1使用element-ui menu组件=>看一下他的效果 =》在根据后台数据动态的生成

 <el-menu
      active-text-color="#ffd043"
      background-color="#545c64"
      class="el-menu-vertical-demo"
      :collapse="isCollapse" //展开和收缩
      :default-active="activePath" //显示点击的导航
      text-color="#fff"
      @open="handleOpen"
      @close="handleClose"
    >
    <!--  -->
    <div v-for="(item,index) in navListData" :key="index">
        <!-- 判断每一项是否有list,有 可以展开, -->
      <el-sub-menu  v-if="item.list"> //有嵌套导航
          <!-- 名称 -->
        <template #title>
          <el-icon><i :class="item.icon"></i></el-icon>
          <span>{{item.name}}</span>
        </template>
        <!-- 内容 -->
        <!-- <el-menu-item-group title="Group Two">
          
        </el-menu-item-group> -->
        <!-- 循环嵌套循环 -->
        <el-menu-item :index="'/home'+ Childrenitem.path" v-for="(Childrenitem,indexC) in item.list" :key="indexC" @click="goPath('/home'+Childrenitem.path)">{{Childrenitem.name}}</el-menu-item>
     
      </el-sub-menu>

      <!--  -->
      <el-menu-item :index="'/home'+item.path"  @click="goPath('/home'+item.path)" v-else>
        <el-icon><i :class="item.icon"></i></el-icon>
        <template #title>{{item.name}}</template>
        <!-- <span>{{item.name}}</span> -->
      </el-menu-item>
      </div>
      <!-- <el-menu-item index="3" >
        <el-icon><document /></el-icon>
        <span>Navigator Three</span>
      </el-menu-item>
      <el-menu-item index="4">
        <el-icon><setting /></el-icon>
        <span>Navigator Four</span>
      </el-menu-item> -->
    </el-menu>

2在根据后台数据动态的生成

放到本地

 

实现点击按钮侧边栏导航展开和收缩

(1)完善样式

功能

1)在头部组件中实现图标条件渲染

```javascript

import { ref } from "vue"; let isShow = ref(false); function showMenus(val) { isShow.value = val; // 修改vuex中的数据 //

} ```

2)我需要将这个数据放到 vuex中

(1)在vue3中使用vuex,

1.1 引入 import{use Store} from'vuex

1.2 获取仓库实例对象 let store = useStore()

1.3 和vue2的操作方法一样

   ```javascript

import { ref } from "vue"; import { useStore } from "vuex"; let isShow = ref(false); let store = useStore(); function showMenus(val) { isShow.value = val; // 修改vuex中的数据 // store.commit("setIsShowNav", val); } ```

3)在侧边栏到中获取到 时时组件

问题:时刻获取到vuex中的数据 必须用watch

//实时监听 store.state.isShowNav 响应式数据
// 
watch(()=>store.state.isShowNav,(newVal,oldVal)=>{
   console.log(newVal);
   isCollapse.value = newVal
})

实现面包屑功能

(1)使用组件完成样式

功能

(1)内容是根据用户点击侧边栏导航生成的

(2)通过路由监听获取到当前的路由信息,添加到面包屑中

1 登录成功之后进入页面=》重定向 仪表板

头部搜索

(1) 默认显示 搜素图标
(2)点击第一次 显示搜素框,在点击隐藏搜索框
  <div class="search">
      <!-- (1) 默认显示 搜素图标
                    (2)点击第一次 显示搜素框,在点击隐藏搜索框
                 -->
      <el-icon @click="isShowInP(true)" v-if="!isshowSearch"><Search /></el-icon>
      <el-icon @click="isShowInP(false)" v-if="isshowSearch"><Search /></el-icon>
      <!-- input -->
      <div class="inputBox" v-if="isshowSearch">
        <input type="text" placeholder="search" />
      </div>
    </div>

import { Search } from "@element-plus/icons-vue";
import {ref} from 'vue'

let isshowSearch = ref(false) //响应式数据

function isShowInP(val){
isshowSearch.value = val
}

头部全屏

//全屏
function fullScr() {
  const docElm = document.documentElement; //全局方法
  if (docElm.requestFullscreen) {
    docElm.requestFullscreen();
  } else if (docElm.msRequestFullscreen) {
    docElm.msRequestFullscreen();
  } else if (docElm.mozRequestFullScreen) {
    docElm.mozRequestFullScreen();
  } else if (docElm.webkitRequestFullScreen) {
    docElm.webkitRequestFullScreen();
  }
}

头部全局字体设置

(1) 就是我们在写一个项目的时候,我们会确定 3种 defaul max min,

defaul:20px

max:30px

min:15px

(2)所有的字体都是动态的属性

实现:

(1)实现点击下拉选项,效果却换

el-dropdown>
        <el-icon><CopyDocument /></el-icon> 
        <template #dropdown>
          <el-dropdown-menu>
            <el-dropdown-item :disabled="isSelectFont==1" @click="isDropdown(1)">default font</el-dropdown-item>
            <el-dropdown-item :disabled="isSelectFont==2" @click="isDropdown(2)">max</el-dropdown-item>
           <el-dropdown-item :disabled="isSelectFont==3" @click="isDropdown(3)">min</el-dropdown-item>
          </el-dropdown-menu>
        </template>
      </el-dropdown>

//字体
let isSelectFont = ref(1)
function isDropdown(val){
    isSelectFont.value = val
}

自定义指令

就是vue提供的指令现在不能满足我的需求

语法:

app.directive('自定义指令的名称',{ 这个指令的作用})  

只用:给我们组要元素

 <div class="me" v-defaultFont="100">
        字体
    </div>

练习: 创建文件的自定义指令

main.js

    app.directive('defaultFont', {
            //
            mounted(el, binding) {//什么时候添加这个指令  ,el:绑定元素的真实dom
                console.log(el, binding); //zbinding:自定义指令接收的值
                el.style.fontSize = 20 + 'px'
            }
        })

优化抽离

(1)创建文件夹directive/index.js

我们先写了一个vue2思维逻辑=》

// import {createApp} from 'vue'

// let app = createApp({}) //重新创建了一个 vue实例,他不是main.js中实例


//   app.directive('defaultFont',{
//     //
//     mounted(el,binding){//什么时候添加这个指令  ,el:绑定元素的真实dom
//       console.log(el,binding); //zbinding:自定义指令接收的值
//       el.style.fontSize=20+'px'
//     }
//   })

解决方法 =》通过 app.use() 来处理

  //vue.use()

//(1) .use()写了一个方法或者对象,如果有一个属性 install,并且这个属性是一个方法
//那么他的第一个参数 当前的vue实例
//获取同一个vue实例
let directiveObj = {
    install(app) { //第一个参数 app
        console.log(app); //当前项目 vue实例=》就是main.js中的实例
        app.directive('defaultFont', {
            //
            mounted(el, binding) {//什么时候添加这个指令  ,el:绑定元素的真实dom
                console.log(el, binding); //zbinding:自定义指令接收的值
                el.style.fontSize = 20 + 'px'
            }
        })
    }
}


export default directiveObj

就是我们这个项目中有三种字体=》自定义指令

//(1) .use()写了一个方法或者对象,如果有一个属性 install,并且这个属性是一个方法
//那么他的第一个参数 当前的vue实例
//获取同一个vue实例
let directiveObj = {
    install(app) { //第一个参数 app
        console.log(app); //当前项目 vue实例=》就是main.js中的实例
        app.directive('defaultFont', {
            //
            mounted(el, binding) {//什么时候添加这个指令  ,el:绑定元素的真实dom
                console.log(el, binding); //zbinding:自定义指令接收的值
                if( binding.value=='default'){
                    el.style.fontSize = 20 + 'px'
                }
                if( binding.value=='max'){
                    el.style.fontSize = 30 + 'px'
                }
                if( binding.value=='min'){
                    el.style.fontSize = 12 + 'px'
                }
               
            }
        })
    }
}

实现全局却换字体

(1)在vuex种定义数据 =》多个组件需要这个数据

   ```j avascript

state: {

 glbFont:'default'

}, mutations: {

setGlbFont(state,data){
   state.glbFont = data  //设置新值
}

}, ```

(2) 在到具体的页面中使用数据

1)获取到vuex中的数据 =》注意 vuex中的数据到setup中获取了不在是响应式了

```javas sript

<template> <div class="dashboard" > 仪表 <!-- 我们页面字体是动态的,是根据我们选择 的

      -->
     <div v-defaultFont="Afont">仪表1</div>
 </div>

</template>

<script setup> import {ref} from 'vue' import {useStore} from 'vuex' let store = useStore() //注意 (1)获取到vuex中的默认数据 //时刻监听数据的改变(vuex)=>视图中页面对应的改变 let Afont = ref(store.state.glbFont) // 这个数据是不是要从vuex中获取 // let Afont = store.state.glbFont // 不是响应式数据 // console.log(Afont ,2222222222); </script>

<style>

</style> ```

(3)在头部全局设置=》就是给vuex 放新的数据

function isDropdown(val) {
  isSelectFont.value = val;
  // 关联 1 默认字体 =>将设置字体放vuex
  if (val == 1) {
    //默认字体
    store.commit("setGlbFont", "default");
    router.replace('/home/dashboard')
  } else if (val == 2) {
    //max
    store.commit("setGlbFont", "max");
     router.replace('/home/dashboard')
  } else {
    //mix
    store.commit("setGlbFont", "min");
    router.replace('/home/dashboard')
  }
}

头部我的

(1)样式处理

功能:

(1)点击跳转

(2)点击退出登录 =》核心我们需要清空本地存放的数据

页面处理仪表板

表格;

=>添加,改,查,删除

(1)完成基本的样式

功能:(1)发送请求获取数据

(2)页面渲染

  ```javascript

import {getTable} from '@/http/api/table' import {reactive} from 'vue'

let tableData = reactive({ list:[] }) getTable('/table',{}).then(res=>{ //获取到数据 if(res.code==200){ tableData.list = res.table } })

  ```

(3)点击删除列表数据

````javascript

// 删除处理 function deleteItem(id) { //(1) 点击删除 ,获取这一项的id=>发送给 后端 =》根据这个id 删除这个数据 ,在发送请求获取table

//(2) 点击删除 ,获取这一项的id=>发送给 后端 =》根据这个id 删除这个数据,=》前端在这个数组中自己删除 //1)获取id // findIndex => 找到数组中的index let index = tableData.list.findIndex((item) => { return item.id == id; }); //前端在这个数组中自己删除 tableData.list.splice(index, 1); //发送请求告诉后端 deleteTable(id); }

function deleteTable(id) { DeleteTable("/delete/table", { id }).then((res) => { console.log(res); if (res.code == 200) { // 提示用户 ElMessage({ showClose: true, message: res.msg, type: "success", }); } else { ElMessage({ showClose: true, message: '删除失败', type: "error", }); } }); } ````

(4)点击编辑

1)完成样式

功能:

(1)点击编辑=>出现编辑模块

(2)获取需要编辑的的默认数据

<template>
  <div class="eidtBox">
    <el-dialog
      v-model="isShow"
      title="Edit"
      width="60%"
      :before-close="handleClose"
    >
      <div class="content">
        <!-- 表单 -->
        <div class="item">
          <div class="left">address</div>
          <div class="right">
            <!--选择器  -->
            <el-select v-model="value" class="m-2" placeholder="Select">
              <el-option
                v-for="item in options"
                :key="item.value"
                :label="item.label"
                :value="item.value"
              />
            </el-select>
          </div>
        </div>
        <!-- 时间 -->
        <div class="item">
          <div class="left">time</div>
          <div class="right">
            <!--选择器  -->
            <el-date-picker
              v-model="value1"
              type="datetime"
              placeholder="Select date and time"
            />
          </div>
        </div>
​
           <!-- status -->
        <div class="item">
          <div class="left">status</div>
          <div class="right">
            <!--选择器  -->
            <el-select v-model="value" class="m-2" placeholder="Select">
              <el-option
                v-for="item in options"
                :key="item.value"
                :label="item.label"
                :value="item.value"
              />
            </el-select>
          </div>
        </div>   
        <!-- status -->
        <div class="item">
          <div class="left">title</div>
          <div class="right">
         <el-input v-model="input" placeholder="Please input" />
          
          </div>
        </div>
      </div>
      <template #footer>
        <span class="dialog-footer">
          <el-button @click="isShow = false">Cancel</el-button>
          <el-button type="primary" @click="isShow = false"
            >Confirm</el-button
          >
        </span>
      </template>
    </el-dialog>
  </div>
</template>
​
<script setup>
// 
import { ref,onMounted } from "vue";
// const dialogVisible = ref(false); //显示隐藏
​
// 接收父组件的组件 =>defineProps
let props = defineProps({
  isShow:{
    type:Boolean
  },
  items:{
    type:Object
  }
})
// onMounted(()=>{
//     console.log(props.items,33333);
// })
const handleClose = (done) => {
  //关闭
  ElMessageBox.confirm("Are you sure to close this dialog?")
    .then(() => {
      done();
    })
    .catch(() => {
      // catch error
    });
};
// address
const value = ref(props.items.address);
​
const options = [
  {
    value: "china",
    label: "china",
  },
  {
    value: "japan",
    label: "japan",
  },
 
];
​
// 时间
const value1 = ref(props.items.date)
</script>
​
<style scoped lang="less">
.eidtBox {
  .content {
    .item {
      display: flex;
      align-items: center;
      margin-top: 10px;
      .left {
        width: 70px;
      }
      .right {
        margin-left: 18px;
      }
    }
  }
}
</style>

(3)点击确定发起请求给后台,=》带上最新修改的数据

(4)成功之后=》重新发送请求=》获取到table 最新的数据

5处理状态

(1) 如果我们的状态是 发布=》在 操作 =》 默认 ,反之

(2)点击发布,发送请求给后台=》页面改变=》默认

6分页

(1)完善样式

(2)看动态的属性

(3)逻辑处理

组件传递数据

父组件向子组件传递数据

defineProps({}) //获取父组件的数据是只读的

const props = defineProps({
  foo: String
})

子组件向父组件传递数据

defineEmits(['自定义事件'])

(1)在子组件中定义事件

 let emit=    defineEmits(['getFather']) //他的返回值就是vue2的emit

(2) 在通过我们在子组件中的按钮触发这个方法

emit('事件',数据)

```javascript

emit('getFather',false) ```

(3)在父组件中接收这个事件

<editItem @getFather="getFather" :items="items.itemObje" :isShow="isShow" v-if="isShow"></editItem>

echarts 在项目中的使用

安装

 npm install echarts --save

使用

(1)对这个元素进行绘画=》dom

<div id="main" style="height:500px"></div><div id="main" style="height:500px"></div>

(2)在当前模块中引入 echarts核心方法

  import * as echarts from 'echarts';

(3)在 onmounted 生命周期中进行 设置 echarts

onMounted(()=>{


// 基于准备好的dom,初始化echarts实例
var myChart = echarts.init(document.getElementById('main'));
// 绘制图表
myChart.setOption({
  title: {
    text: 'ECharts 入门示例'
  },
  tooltip: {},
  xAxis: {
    data: ['衬衫', '羊毛衫', '雪纺衫', '裤子', '高跟鞋', '袜子']
  },
  yAxis: {},
  series: [
    {
      name: '销量',
      type: 'bar',
      data: [5, 20, 36, 10, 10, 20]
    }
  ]
});
 })

注意每次使用echarts 时候看一下他的属性

 export function request(url,data={},method='GET'){
    return new Promise((resolve,reject)=>{
        发送请求
        wx.request({
            url:'https//.com'+url,
            method,
            data,
            success(res){
                resolve(res.data)
            }
            fail(err){
                console.log(err)
        }
        })
    })
}

import {request} from ' '
requset('/list'给了默认不用写).then(res=>{
    console.log(res)
})

微信小程序

1:官网:微信公众平台

(1)注册微信公众平台账号=》有账号

(2) 登录(需要微信扫码) =》下载微信开发工具 =》地址

选择 稳定版

(3)添写我们自己小程序的相关消息(不要选择游戏)=》在首页

(4)在开发管理中=》开发设置=》复制我们的appid=> wx9392ba9bdb726f42

2:开发

认识我们微信开发者工具

(1)创建项目

分析微信小程序目录结构

pages => views 写页面的

注意:在微信小程序

布局:.wxml 文件(写html)

逻辑 :.js文件

css: .wxss文件

utils =》公共方法

app.js=>main.js=》小程序入口文件(小程序逻辑)

app.json=>小程序的配置文件

app.wxss=>x小程序公共样式

project.configproject.json =>小程序配置文件

sitemapsitemap.json =>设置小程序

三:微信小程序全局配置

app.json(微信小程序全局配置)

(1)配置页面

pages:[ //相对于vue中的路由表=》routes 页面路由 ] window:设置窗口 全局配置 { backgroundTextStyle: 下拉 loading 的样式,仅支持 dark / light navigationBarBackgroundColor:导航栏背景色 }

"sitemapLocation": "sitemap.json" //是否允许微信可以搜索到微信小程序

taber: (1)其中 list 接受一个数组,只能配置最少 2 个、最多 5 个 tab。 例子: "tabBar":{ "list": [ { "pagePath":"pages/home/index", //页面路径 "text":"music" //内容 }, { "pagePath":"pages/logs/logs", "text":"video" } ] }, ```

全局配置=》app.json,对小程序所有的页面进行配置,如果某个页面需要自己的配置,给自己独立配置

页面配置:

就是每个页面自己的.json文件=》覆盖全局样式

wxml语法 =》vue指令

(1)获取数据(data) =》{{}}

(2)添加事件=>bind,catch =》@

(3)事件的处理

  1)在pages中添加方法,就是我们写的处理事件
     
     获取数据data=》this.data.属性
     在微信小城中修改数据=>this.setData({修改的属性:值})  

(4)条件渲染

生命周期

从创建到消亡的各各过程,生命周期钩子函数

从零搭建微信小程序

1创建微信小程序项目=>通过微信开发者工具

2:安装 vant ui组件库 地址

(1) 安装

npm i @vant/weapp -S --production

( 2)修改 app.json

将 app.json 中的 "style": "v2" 去除,小程序的新版基础组件强行加上了许多样式,难以覆盖,不关闭将造成部分组件样式混乱。

(3) 在project.config.json 修改

(4) npm 构建

成功:vant在微信小程序中安装成功 =》有 miniprogram_npm

注意:如果构成不成功=》 所以新版本的miniprogramNpmDistDir配置为'./'即可

3: 微信小程序页面使用vant组件

(1)vant ui 组件在微信小程序中的某个页面使用

来到 这个页面.json文件中进行注册

  "usingComponents": {
    "van-notice-bar": "@vant/weapp/notice-bar/index"
​
  }

就可以使用了

4:微信小程序请求的封装

(1)wx.request({配置对象})

   wx.request({
       url: 'https://www.fastmock.site/mock/1ccbb3fc0999e36f940a63ab4ba7d971/flower/slideshow',//地址
       method:'GET',//不行默认get,
       data:{}, //请求参数
       success(res){ //请求成功 res
         console.log(res);
       },
       fail(err){//请求失败
​
       },
       complete(res){ //请求完成
​
       }
​
     })

(2) 微信小程序所有的请求,必须是https ,还有在微信公共平台中首页=》开发管理=》开发设置

添加请求域名

(3)封装请求=》在我们创建的http/index.js

​
​
//封装请求
​
​
export  function request(url,data={},method='GET'){
​
    return new Promise((resolve,reject)=>{
        //发送请求=>微信小程序的请求
        wx.request({
          url: 'https://www.fastmock.site/mock/1ccbb3fc0999e36f940a63ab4ba7d971/flower'+url,
          method,
          data,
          success(res){
            resolve(res.data)//后台给的数据
          },
          fail(err){
              console.log(err);
          }
        })
    })
}
​
​
​
// request(url,data,method).then(res=> {res请求过来的数据})
​
//封装请求
​
​

五:home页面

(1)分析:布局

注意:在微信小程序,不要使用iconfont(外链的方法) =》 使用 iconfont 图片

使用 iconfont =>下载到本地

(2) 处理底部

使用vant =》tabbar

(3)创建hoem 页面 中的组件

1)在和pages同级的文件夹 创建 =》通过components

2)开始创建组件

3)来到我们home 进行引入注册 => .json文件

  "usingComponents": {
    "van-tabbar": "@vant/weapp/tabbar/index",
    "van-tabbar-item": "@vant/weapp/tabbar-item/index",
    "index-item":"../../components/index/index",
    "index-class":"../../components/class/index",
    "index-community":"../../components/shequ/index",
    "index-me":"../../components/me/index",
    "index-cart":"../../components/cart/index"
  }

4)在页面中使用

(4)功能 点击底部却换 内容

六:首页

(1) 布局

(2)发送请求渲染头部分类

(3)发送请求渲染轮播图

七:购物车

(1 )处理样式,布局

功能:(1) 计算总价:

1) 选中的计算 =>页面加载默认处理

2)选中取消 ,同步计算的总价

3)处理点击每一项的数据

(2)处理结算 =》就是我们选中的个数

(3)全选=》(1)全部选中 (2)全部不选中 (3) 默认选中

const app = getApp() //获取全局数据
Component({
  /**
   * 组件的属性列表
   */
  properties: {

  },

  /**
   * 组件的初始数据
   */
  data: {
    cardList: [], //购物车列表
    checked: true, //全选
    allP: 0, // 总价
    selectNums:0  //结算
  },

  /**
   * 组件的方法列表
   */
  methods: {
    // 全选
    onChange() {

      //(1)默认选中

       //(2) 让 cardList 每一项和 全选一致
       for(let i =0;i<this.data.cardList.length;i++){
        this.data.cardList[i].checked =  !this.data.checked
       }
      this.setData({
        checked: !this.data.checked,
        cardList:this.data.cardList
      })

      // 合计
      this.getAll()
      this.getSelectNum()
    },
    // 获取默认购物车的数据
    getDefaultData() {
      // 在组件实例进入页面节点树时执行
      console.log(app);
      //情况:进入购物车有数据,默认选中
      //选中是通过 =》checkbox =》value =>true

      //我在获取数据的时候,给每一项添加一个属性checked:true

      if (app.globalData.cartList.length == 0) return false

      for (let i = 0; i < app.globalData.cartList.length; i++) {
        app.globalData.cartList[i].checked = true
      }
      this.setData({
        cardList: app.globalData.cartList,
        selectNums:app.globalData.cartList.length
      })


    },
    //计算总价
    getAll() {
      // 就是遍历 数组=》checked = >true
      let all = 0
      for (let i = 0; i < this.data.cardList.length; i++) {
        if (this.data.cardList[i].checked) {
          all = all + Number(this.data.cardList[i].pic) * this.data.cardList[i].nums
        }
      }
      //赋值
      this.setData({
        allP: all
      })


    },
    //点击列表中的每一项选中 和没有选中处理
    changeAllSelect(){
       //就是用来判断是否购物车列表中的 选中状态是否全部为 true
    let index =   this.data.cardList.findIndex(( item)=>{
          return   item.checked == false //符合条件 返回索引 不 符合条件 -1
       })

       if(index==-1){
         this.setData({
          checked: true
         })
       }else{
        this.setData({
          checked: false
         })
       }

    },
    //处理列表选中
    onChangeItem(e) {
      console.log(e);
      //(1) 获取到数组的索引
      let index = e.currentTarget.dataset.index
      //(2)获取到当前的这一项的状态
      this.data.cardList[index].checked = !this.data.cardList[index].checked

      this.setData({
        cardList: this.data.cardList
      })
      // 计算总价
      this.getAll()
      
      this.getSelectNum()

      this.changeAllSelect()
    },
    reduce(e) {
      //(1) 获取到当前列表中那一项的nums
      let index = e.currentTarget.dataset.index
      //(2)进行减一 注意 如果为1
      if (this.data.cardList[index].nums > 1) {
        this.data.cardList[index].nums = this.data.cardList[index].nums - 1

        this.setData({
          cardList: this.data.cardList
        })

        // 计算总价
        this.getAll()
      }
    },
    add(e) {
         //(1) 获取到当前列表中那一项的nums
         let index = e.currentTarget.dataset.index
         //(2)进行累加 
         this.data.cardList[index].nums = this.data.cardList[index].nums + 1

         this.setData({
          cardList: this.data.cardList
        })

         // 计算总价
         this.getAll()
       
    },
    //需要结算的个数
    getSelectNum(){
      let num = 0
      for (let i = 0; i < this.data.cardList.length; i++) {
        if (this.data.cardList[i].checked) { //需要结算的个数
          num = num + 1
        }
      }
      this.setData({
        selectNums: num
      })
    }
  },
  //当我们这个组件加载的时候 =》获取全局数据
  lifetimes: {
    attached: function () {
      this.getDefaultData()
      this.getAll()

    },
    detached: function () {
      // 在组件实例被从页面节点树移除时执行
    },
  },

})

(4) 点击编辑

1)出现可以删除的页面

 ```javascript

// 点击编辑 delete(){ //(1) 出现完成

  //(2)出现完成=>选中的状态全部变成没有选中

  //(3) 总价隐藏 显示删除
  if(this.data.isTop){
      this.noSelect()
  }
  this.setData({
    isTop:!this.data.isTop
  })

}, ```

2)点击删除=》删除购物车中的数据=》根据我们选中的状态进行删除

  // 删除购物车中的数据
  deleteCart(){
       //1 遍历购物车数据,查看你是否选中,如果选中,直接删除

      for(let i =this.data.cardList.length-1;i>=0;i--){
        if(this.data.cardList[i].checked){
          this.data.cardList.splice(i,1)
        }
      }
     console.log(this.data.cardList);
      this.setData({
        cardList:this.data.cardList
      })
       
  },

八:请求优化

//封装请求

//请求优化
//(1)就是加载页面的的时候我们需告诉用户正在发送请求,
// 如果请求没有完成,提示用户

//问题:我这个首页有4请求

// 我这个页面刚刚发送请求的时候 第一个请求 出现弹框

// 我这个页面最后一个请求 完成 隐藏

let requsetlist = 0

export  function request(url,data={},method='GET'){
  requsetlist++  //3
  wx.showLoading({
    title: '加载中',
  })
    return new Promise((resolve,reject)=>{
        wx.request({
          url: 'https://www.fastmock.site/mock/1ccbb3fc0999e36f940a63ab4ba7d971/flower'+url,
          method,
          data,
          success(res){
            resolve(res.data)//后台给的数据
          },
          fail(err){
              console.log(err);
          },
          complete(res){ //这个请求完成
              
              if(--requsetlist==0){
                console.log(requsetlist);
                wx.hideLoading()
              }
          }
     
        })
    })
}



// request(url,data,method).then(res=> {res请求过来的数据})

//为小程序请求的封装

// (1)抽离wx:request(),实现所有微信小程序请求共有一个方法,
//配置服务器跟地址, 优化请求,比如添加加载效果
// 给所有的页面请求添加token

九:微信小程序登录流程

(1)需要使用过wx.login((res)=>{}) //获取到token

(2)发送请求给后端=》session_key=>标识

(3)得到这个session_key 保存本地

(4)在所有业务请求需要添加session_key

实现步骤

(1)微信小程序一运行,就需要,=》app.json中

  //登录
  login(){
    //(1)发送 res.code 到后台换取 openId, sessionKey, unionId
    console.log(1000);
    wx.login({
      success:res=>{
        console.log(res.code); //获取到code
        // (2)发送请求=》后端
        request('/login',{code:res.code},'POST').then(res=>{
          console.log(res);//获取到session_key

          //(3)保存token
          wx.setStorageSync({
            key:"token",
            data:res.session_key
          })
          //(4)在请求封装中获取token,添加到头部
        })
      }
    })
  },

(2)去我们的请求 封装添加token

//获取token

 function getToken(){
 return   wx.getStorageSync('token')
}

 header:{
            token:getToken()? getToken():''
          },

10:支付流程

微信小程序的支付

(1)点击付款 =》给后端发送请求,=》后端返回数据 =》调用微信支付

1:点击付款=》获取需要付款的相关数据 =》 发送请求=》[{}] =>返回数据

    ```javascript

request("/支付",{参数:相关产品的信息},).then(res=>{ if(res.code == 200) { wx.requestPayment({ timeStamp: 'timeStamp', nonceStr: 'nonceStr', package: ' package', signType: 'MD5', paySign: 'paySign', success (res) { console.log(“支付成功) }, fail (res) { } }) }

}) ```

11:上线版本

react是什么

React 是一个声明式,高效且灵活的用于构建用户界面的 JavaScript 库

npx create-react-app my-app
cd my-app
npm run start

jsx

就是js和html的合并

函数式组件

函数式 1.就是一个函数 2.一定要有返回值

生命周期

1. Mounting(挂载阶段)——创建构造函数并初始化,让我们在页面加载完成前后做一些事情

2. Updating(运行阶段)——状态更新引起的变化,更新页面UI显示或数据更改

3. Unmounting(卸载阶段)——销毁一个组件,销毁前暴露出一个事件,让我们可以在组件销毁前做一些逻辑的处理,比如组件销毁后,也要将组件的定时器销毁,减少内存占用

react更新机制

重新渲染组件

useState

相当于vue3的ref和reactive 修改方法不会合并

useEffect

组件挂载后 组件更新 组件的卸载

依赖性空数组用来发送网络请求

依赖性里面写数据相当于vue的watch

组件卸载=》在调用下一个useEffect的时候,先执行上一个useEffect 处理函数的返回值

受控组件是什么

用state来获取和设置输入元素值的组件,称之为受控组件。 拿到from表单获取到用户数据就是受控组件

hook

memo 缓存组件

useMome 相当于计数属于可以缓存属性

useref 获取元素真实dom

react forwarRef 转发真实Dom父组件获取子组件 佛窝的ref

use Imper ativehandle 重要的方法 严格的数据格式要求 in破的哎xt喊得了

react createconText 相对于vue中的provide提供数据的组件不过嵌套多深都可以拿到 克瑞t康txt

use context子组件接收父组件传递消息

uselayoutEffect 微任务 哥哥是宏任务 累熬t

usereducer 是usestate的晋升版本 规定了处理方法。确定一些数据不能随便修改 瑞丢舍

usecallback 缓存方法的 康摆克

redux

主要用于我们的状态管理。 16 17版本 优势 单一数据源 状态是只读的 状态的改变只能通过action 唯一改变 state 的方法就是触发 action

三个核心属性:state reducer

工作流 通过我们的state存放我们的数据 通过actions修改我们的数据 reducer会得到新的数据 在到我们的页面上进行使用通过我们的subscribe进行订阅

reducer=>就是一个方法=>有两个参数=>数据,行为 vue中的m和s进行合并的 瑞丢瑟

核心

state 存放数据的
​
import {createstore} from 'redux'
createstore=>创建仓库
​
reducer=>定义的行为 处理方法和修改数据 只能写同步 就是vuex里面的m和s关联了

combineReducers

为什么?:问题就是我这个项目用到的全局存放的数据 很多,那么我们那个reducer 很大,因此reducer 很大,代码很冗余

作用:可以合并多个reducer 成为一个reducer=>模块处理

react-redux

可以让我们的redux不需要useEffer进行订阅就是响应式的 产生关联

import {useDispatch,useSelector} from 'react-redux';

useSelector=>获取仓库中的数据 丝莱克t

用法=》 useSelector(仓库store=>store.reducer的属性.名称)

useDispatch=>dispatch=>触发actions 派发的

let dispatch = useDispatch() //提供dispatch方法

在index.js中提供全局store

import { store } from './redux/index'
//引入 provider
import { Provider } from 'react-redux'
​
ReactDOM.render(
    //Provider 提供器,接受store,被<Provider>组件包裹的组件都能使用store中传递过来的数据
  <Provider store={store}>
    <App />
  </Provider>
  ,
  document.getElementById('root')
);

redux-thunk

什么是 redux-thunk?

(1)redux-thunk 是一个中间件,专门用来解决 action 中的异步处理。

(2) redux提供了一个方法 applyMiddleware 用来使用中间件。 儿噗赖 梅都未ao

(3) redux-thunk 的安装方法:cnpm i redux-thunk -S

import { createStore,applyMiddleware } from 'redux'
import reduxThunk from 'redux-thunk'
import reducers from './reducers'
​
// 创建 store 的时候,使用中间件
const store =createStore(reducers,applyMiddleware(reduxThunk));
export default store;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值