Vue-学习笔记-3

Vue

一、Mixin混入的基础语法

<script>
  // mixin 混入
  // 组件 data, methods 优先级高于 mixin data, methods 优先级
  // 生命周期函数,先执行 mixin 里面的,再执行组件里面的
  // 自定义的属性,组件种的属性优先级高于 mixin 属性的优先级
  const myMixin = {
    number: 1
  }

  const app = Vue.createApp({
    mixins: [myMixin],
    number: 2,
    template: `
      <div>
        <div>{{this.$options.number}}</div>
      </div>
    `
  });

  app.config.optionMergeStrategies.number = (mixinVal, appValue) => {
    return mixinVal || appValue;
  }

  const vm = app.mount('#root');
</script>

二、开发自定义指令

<script>
  // 自定义指令 directive

  const app = Vue.createApp({
    data() {
      return {
        distance: 110
      }
    },
    template: `
      <div>
        <div v-pos:right="distance" class="header">
          <input />
        </div>
      </div>
    `
  });

  app.directive('pos', (el, binding) => {
    el.style[binding.arg] = (binding.value + 'px');
  })

  const vm = app.mount('#root');
</script>

三、Teleport传送门功能

<style>
    .area {
      position: absolute;
      left: 50%;
      top: 50%;
      transform: translate(-50%, -50%);
      width: 200px;
      height: 300px;
      background: green;
    }
    .mask {
      position: absolute;
      left: 0;
      right: 0;
      top: 0;
      bottom: 0;
      background: #000;
      opacity: 0.5;
      color: #fff;
      font-size: 100px;
    }
  </style>
  <script src="https://unpkg.com/vue@next"></script>
</head>
<body>
  <div id="root"></div>
  <div id="hello"></div>
</body>
<script>
  // teleport 传送门
  const app = Vue.createApp({
    data() {
      return {
        show: false,
        message: 'hello'
      }
    },
    methods: {
      handleBtnClick() {
        this.show = !this.show;
      }
    },
    template: `
      <div class="area">
        <button @click="handleBtnClick">按钮</button>
        <teleport to="#hello">
          <div class="mask" v-show="show">{{message}}</div>
        </teleport>
      </div>
    `
  });

  const vm = app.mount('#root');
</script>

四、render函数

<script>
  // render function
  // template -> render -> h -> 虚拟DOM(JS对象)-> 真实 DOM -> 展示到页面上
  const app = Vue.createApp({
    template: `
      <my-title :level="2">
        hello dell
      </my-title>
    `
  });

  app.component('my-title', {
    props: ['level'],
    render() {
      const { h } = Vue;
      return h('h' + this.level, {}, [
        this.$slots.default(),
        h('h4', {}, 'dell')
      ])
    }
  })

  const vm = app.mount('#root');
</script>

五、插件的定义和使用

<script>
  // plugin 插件, 也是把通用性的功能封装起来
  const myPlugin = {
    install(app, options) {
      app.provide('name', 'Dell Lee');
      app.directive('focus', {
        mounted(el) {
          el.focus();
        }
      })
      app.mixin({
        mounted(){
          console.log('mixin')
        }
      })
      app.config.globalProperties.$sayHello = 'hello world';
    }
  }

  const app = Vue.createApp({
    template: `
      <my-title />
    `
  });

  app.component('my-title', {
    inject: ['name'],
    mounted() {
      console.log(this.$sayHello);
    },
    template: `<div>{{name}}<input v-focus /></div>`
  })

  app.use(myPlugin, { name: 'dell'});

  const vm = app.mount('#root');
</script>

六、数据校验插件

<script>
  // 对数据做校验的插件
  const app = Vue.createApp({
    data() {
      return { name: 'dell', age: 23}
    },
    rules: {
      age: {
        validate: age => age > 25,
        message: 'too young, to simple'
      },
      name: {
        validate: name => name.length >= 4,
        message: 'name too short'
      }
    },
    template: `
      <div>name:{{name}}, age:{{age}}</div>
    `
  });

  const validatorPlugin = (app, options) => {
    app.mixin({
      created() {
        for(let key in this.$options.rules) {
          const item = this.$options.rules[key];
          this.$watch(key, (value) => {
            const result = item.validate(value);
            if(!result) console.log(item.message);
          })
        }
      }
    })
  }

  app.use(validatorPlugin);
  const vm = app.mount('#root');
</script>

七、Setup函数使用

<script>
  // 对数据做校验的插件
  const app = Vue.createApp({
    template: `
      <div @click="handleClick">{{name}}</div>
    `,
    methods: {
      test() {
        console.log(this.$options.setup());
      }
    },
    mounted() {
      this.test();
    },
    // created 实例被完全初始化之前
    setup(props, context) {
      return {
        name: 'dell',
        handleClick: () => {
          alert(123)
        }
      }
    }
  });
  const vm = app.mount('#root');
</script>

八、ref、reactive响应式引用的用法和原理、toRef以及context参数

<script>
  // ref, reactive 响应式的引用
  // 原理,通过 proxy 对数据进行封装,当数据变化时,触发模版等内容的更新
  // ref 处理基础类型的数据
  // reactive 处理非基础类型的数据
  const app = Vue.createApp({
    template: `
      <div>{{name}}</div>
    `,
    setup(props, context) {
      // const { ref } = Vue;
      // proxy , 'dell' 变成 proxy({value: 'dell'}) 这样的一个响应式引用
      // let name = ref('dell');
      // setTimeout(() => {
      //   name.value = 'lee'
      // }, 2000)
      // return { name }

      const { reactive, readonly, toRefs } = Vue;
       // proxy , { name: 'dell'} 变成 proxy({ name: 'dell'}) 这样的一个响应式引用
      const nameObj = reactive({name: 'dell', age: 28});
      setTimeout(() => {
        nameObj.name = 'lee'
      }, 2000)
      // toRefs proxy({ name: 'dell', age: 28}), { 
      //  name: proxy({ value: 'dell'}),
      //  age: proxy({value: 28})
      // }
      const { name, age } = toRefs(nameObj);
      return { name }
    }
  });
  const vm = app.mount('#root');
</script>

九、使用Composition API开发Todolist

<script>
  // 关于 list 操作的内容进行了封装
  const listRelativeEffect = () => {
    const { reactive } = Vue;
    const list = reactive([]);
    const addItemToList = (item) => {
      list.push(item);
    }
    return { list, addItemToList }
  }

  // 关于 inputValue 操作的内容进行了封装
  const inputRelativeEffect = () => {
    const { ref } = Vue;
    const inputValue = ref('');
    const handleInputValueChange = (e) => {
      inputValue.value = e.target.value
    }
    return { inputValue, handleInputValueChange}
  }

  const app = Vue.createApp({
    setup() {
      // 流程调度中转
      const { list, addItemToList } = listRelativeEffect();
      const { inputValue, handleInputValueChange} = inputRelativeEffect();
      return {
        list, addItemToList,
        inputValue, handleInputValueChange
      }
    },
    template: `
      <div>
        <div>
          <input :value="inputValue" @input="handleInputValueChange" />
          <button @click="() => addItemToList(inputValue)">提交</button>
        </div>
        <ul>
          <li v-for="(item, index) in list" :key="index">{{item}}</li>
        </ul>
      </div>
    `,
  });
  
  const vm = app.mount('#root');
</script>

十、computed方法生成计算属性

<script>
  // computed 计算属性
  const app = Vue.createApp({
    setup() {
      const { reactive, computed } = Vue;
      const countObj = reactive({ count: 0});
      const handleClick = () => {
        countObj.count += 1;
      }
      let countAddFive = computed({
        get: () => {
          return countObj.count + 5;
        },
        set: (param) => {
          countObj.count = param - 5;
        }
      })

      setTimeout(() => {
        countAddFive.value = 100;
      }, 3000)

      return { countObj, countAddFive, handleClick }
    },
    template: `
      <div>
        <span @click="handleClick">{{countObj.count}}</span> -- {{countAddFive}}
      </div>
    `,
  });
  
  const vm = app.mount('#root');
</script>

十一、watch 和 watchEffect 的使用和差异性

<script>
  // watch 侦听器
  // watchEffect 侦听器,偏向于 effect
  const app = Vue.createApp({
    setup() {
      const { reactive, watch, watchEffect, toRefs } = Vue;
      const nameObj = reactive({
        name: 'dell', englishName: 'lee'
      })
      // 具备一定的惰性 lazy
      // 参数可以拿到原始和当前值
      // 可以侦听多个数据的变化,用一个侦听器承载
      watch([() => nameObj.name, () => nameObj.englishName], ([curName, curEng], [prevName, preEng]) => {
        console.log('watch', curName, prevName, '---', curEng, preEng);
      }, { immediate: true })

      // 立即执行,没有惰性 immediate
      // 不需要传递你要侦听的内容,自动会感知代码依赖,不需要传递很多参数,只要传递一个回调函数
      // 不能获取之前数据的值
      // const stop = watchEffect(() => {
      //   console.log(nameObj.name);
      //   console.log(nameObj.englishName);
      //   setTimeout(() => {
      //     stop();
      //   }, 5000)
      // })

      const { name, englishName } = toRefs(nameObj);

      return { name, englishName }
    },
    template: `
      <div>
        <div>
          Name: <input v-model="name"> 
        </div>
        <div>
          Name is {{name}}
        </div>
        <div>
          EnglishName: <input v-model="englishName"> 
        </div>
        <div>
          EnglishName is {{englishName}}
        </div>
      </div>
    `,
  });
  
  const vm = app.mount('#root');
</script>

十二、生命周期函数的新写法

<script>

  const app = Vue.createApp({
    // beforeMount => onBeforeMount
    // mounted => onMounted
    // beforeUpdate => onBeforeUpdate
    // beforeUnmount => onBeforeUnmount
    // unmouted => onUnmounted
    setup() {
      const {
        ref, onBeforeMount, onMounted, onBeforeUpdate, onUpdated,
        onRenderTracked, onRenderTriggered
      } = Vue;
      const name = ref('dell')
      onBeforeMount(() => {
        console.log('onBeforeMount')
      })
      onMounted(() => {
        console.log('onMounted')
      })
      onBeforeUpdate(() => {
        console.log('onBeforeUpdate')
      })
      onUpdated(() => {
        console.log('onUpdated')
      })
      // 每次渲染后重新收集响应式依赖
      onRenderTracked(() => {
        console.log('onRenderTracked')
      })
      // 每次触发页面重新渲染时自动执行
      onRenderTriggered(() => {
        console.log('onRenderTriggered')
      })
      const handleClick = () => {
        name.value = 'lee'
      }
      return { name, handleClick }
    },
    template: `
      <div @click="handleClick">
        {{name}}
      </div>
    `,
  });
  
  const vm = app.mount('#root');
</script>

十三、Provide,Inject,模版 Ref 的用法

<script>
  // provide, inject
  // dom ref
  // const app = Vue.createApp({
  //   setup() {
  //     const { provide, ref, readonly } = Vue;
  //     const name = ref('dell');
  //     provide('name', readonly(name));
  //     provide('changeName', (value) => {
  //       name.value = value;
  //     });
  //     return { }
  //   },
  //   template: `
  //     <div>
  //       <child />
  //     </div>
  //   `,
  // });

  // app.component('child', {
  //   setup() {
  //     const { inject } = Vue;
  //     const name = inject('name');
  //     const changeName = inject('changeName');
  //     const handleClick = () => {
  //       changeName('lee');
  //     }
  //     return { name, handleClick }
  //   },
  //   template: '<div @click="handleClick">{{name}}</div>'
  // })

  // CompositionAPI 的语法下,获取真实的 DOM 元素节点
  const app = Vue.createApp({
    setup() {
      const { ref, onMounted } = Vue;
      const hello = ref(null);
      onMounted(() => {
        console.log(hello.value);
      })
      return { hello }
    },
    template: `
      <div>
        <div ref="hello">hello world</div>
      </div>
    `,
  });
  
  const vm = app.mount('#root');
</script>

十四、VueCLI 的使用和单文件组件

1.先安装node.js
2.node -v
3.安装npm、nrm、nrm ls
4.如果先前安装过脚手架,请先卸载再安装新的。
5.使用脚手架创建vue项目。
6.启动项目,浏览器查看端口。

App.vue

<template>
  <img alt="Vue logo" src="./assets/logo.png">
  <HelloWorld msg="Welcome to Your Vue.js App"/>
</template>

<script>
// 单文件组件
import HelloWorld from './components/HelloWorld.vue'

export default {
  name: 'App',
  components: {
    HelloWorld
  },
}
</script>

<style>

</style>

man.js

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

createApp(App).mount('#app')

HelloWorld.vue

<template>
  <h1>{{ msg }}</h1>
</template>

<script>
export default {
  name: 'HelloWorld',
  props: {
    msg: String
  }
}
</script>

<style>
</style>

十五、使用单文件组件编写 TodoList

Listitem.vue

<template>
  <li class="button">{{ msg }}</li>
</template>

<script>
export default {
  name: 'ListItem',
  props: {
    msg: String
  }
}
</script>

<style>
</style>

App.vue

<template>
  <div>
    <input v-model="inputValue" />
    <button class="button" @click="handleAddItem">提交</button>
  </div>
  <ul>
    <list-item
      v-for="(item, index) in list"
      :key="index"
      :msg="item"
    />
  </ul>
</template>

<script>
import { reactive, ref } from 'vue';
import ListItem from './components/ListItem';

export default {
  name: 'App',
  components: { ListItem },
  setup() {
    const inputValue = ref('');
    const list = reactive([]);

    const handleAddItem = () => {
      list.push(inputValue.value);
      inputValue.value = '';
    };
    return { handleAddItem, inputValue, list }
  }
}
</script>

<style>
  .button {
    margin-left: 20px;
    color: red;
  }
</style>

main.js

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

createApp(App).mount('#app')

十六、Vue-Router 路由的理解和使用

index.js

import { createRouter, createWebHashHistory } from 'vue-router'
import Home from '../views/Home.vue'
import Login from '../views/Login.vue'

const routes = [
  {
    path: '/',
    name: 'Home',
    component: Home
  },
  {
    path: '/login',
    name: 'Login',
    component: Login
  },
  {
    path: '/about',
    name: 'About',
    // 异步加载路由
    component: () => import(/* webpackChunkName: "about" */ '../views/About.vue')
  }
]

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

export default router

App.vue

<template>
  <div id="nav">
    <!-- router-link 是跳转路由的标签 -->
    <router-link to="/">Home</router-link> |
    <router-link to="/about">About</router-link> |
    <router-link to="/login">Login</router-link>
  </div>
  <!-- router-view 负责展示当前路由对应的组件内容 -->
  <router-view/>
</template>

<style></style>

main.js

import { createApp } from 'vue'
import App from './App.vue'
import router from './router'

// 路由是指根据 url 的不同,展示不同的内容
createApp(App).use(router).mount('#app')

十七、VueX的语法

router/ index.js

import { createRouter, createWebHashHistory } from 'vue-router'
import Home from '../views/Home.vue'

const routes = [
  {
    path: '/',
    name: 'Home',
    component: Home
  },
  {
    path: '/about',
    name: 'About',
    component: () => import(/* webpackChunkName: "about" */ '../views/About.vue')
  }
]

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

export default router

store/ index.js

import { createStore } from 'vuex'
// VueX 数据管理框架
// VueX 创建了一个全局唯一的仓库,用来存放全局的数据
export default createStore({
  state: { name: 'dell' },
  // mutation 里面只允许写同步代码,不允许写异步代码
  // commit 和 mutation 做关联
  mutations: {
    change(state, str) {
      state.name = str;
    }
  },
  // dispatch 和 actions 做关联
  actions: {
    // change(store, str) {
    //   setTimeout(() => {
    //     store.commit('change', str)
    //   }, 2000)
    // }
  }
})

About.vue

<template>
  <div class="about">
    <h1 @click="handleClick">This is an about page</h1>
    <h1>{{myName}}</h1>
  </div>
</template>

<script>
export default {
  name: 'Home',
  computed: {
    myName() {
      return this.$store.state.name;
    }
  },
  methods: {
    handleClick() {
      // 1. dispatch 方法,派发一个 action,名字叫做change
      // 2. 感知到 change 这个action,执行store 中 actions 下面的 change 方法
      // 3. commit 提交一个叫做 change 的数据改变
      // 4. mutation 感知到提交的change改变,执行 change 方法改变数据
      this.$store.commit('change', 'hello world');
    }
  }
}
</script>

十八、CompositionAPI 中使用 VueX

store/ index.js

import { createStore } from 'vuex'
export default createStore({
  state: { name: 'dell' },
  mutations: {
    changeName(state, str) {
      state.name = str;
    }
  },
  actions: {
    getData(store) {
      setTimeout(() => {
        store.commit('changeName', 'hello')
      }, 2000)
    }
  }
})

About.vue

<template>
  <div class="about">
    <h1 @click="handleClick">This is an about page</h1>
    <h1>{{name}}</h1>
  </div>
</template>

<script>
import { toRefs } from 'vue';
import { useStore } from 'vuex';
export default {
  name: 'Home',
  setup() {
    const store = useStore();
    const { name } = toRefs(store.state);
    const handleClick = () => {
      store.dispatch('getData')
    }
    return { name, handleClick }
  }
}
</script>·

十九、使用axios发送ajax请求

index.js

import { createStore } from 'vuex'
import axios from 'axios';
export default createStore({
  state: { name: 'dell' },
  mutations: {
    changeName(state, str) {
      state.name = str;
    }
  },
  actions: {
    getData(store) {
      axios.post('https://www.fastmock.site/mock/ae8e9031947a302fed5f92425995aa19/jd/api/user/register')
      .then((response) => {
        const msg = response.data.message;
        store.commit('changeName', msg)
      })
    }
  }
})

About.vue

<template>
  <div class="about">
    <h1 @click="handleClick">This is an about page</h1>
    <h1>{{name}}</h1>
  </div>
</template>

<script>
// https://www.fastmock.site/mock/ae8e9031947a302fed5f92425995aa19/jd/api/user/register
import { toRefs } from 'vue';
import { useStore } from 'vuex';
export default {
  name: 'Home',
  setup() {
    const store = useStore();
    const { name } = toRefs(store.state);
    const handleClick = () => {
      store.dispatch('getData')
    }
    return { name, handleClick }
  }
}
</script>·
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值