zoukankan      html  css  js  c++  java
  • VUE 3.0 初体验之路

    码文不易啊,转载请带上本文链接呀,感谢感谢 https://www.cnblogs.com/echoyya/p/14394057.html


    在2020年9月中旬,vue.js发布了3.0正式版,在不久的将来,VUE3.0 也终将成为大前端的必然趋势,

    环境搭建

    1. node 版本要求: Node.js8.9 或更高版本 ,输入 node -v 查看node版本

    2. vue-cli 版本:达到 vue-cli4.5.0 以上,可创建vue3.0的项目,支持体验vue3.0的新特性,(3.x Preview),vue -V 查看脚手架版本

    3. 终端输入: vue create project_name

    核心知识


    一、组件的定义和使用

    组件:是维护单一功能,可复用的单个个体,相同的样式及逻辑即可抽离成组件,方便维护,复用性增强。也是vue3.0项目中,最核心的概念

    defineComponent:vue3.0中提供了一个函数返回传递给它的对象,最重要的是:在TypeScript下,给予了组件 正确的参数类型推断 。此处先不展开介绍,后续会总结 vue3.0 + ts。

    setup:组件的启动函数,两个参数: props(父组件传递的数据)content ( 上下文对象),最后return 定义的数据,方法,钩子函数等,且setup中 没有this,不能访问this

    <script>
    
        import { defineComponent } from 'vue'
        
        export default defineComponent ({
          setup (props, content) {
            // TODO 数据,方法,钩子函数等
            return { }
          }
        })
    
    </script>
    

    二、数据的定义和使用

    1. ref定义单个数据,接受一个参数值并返回一个响应式且可改变的 ref 对象。ref 对象拥有一个指向内部值的单一属性 .value
    import { ref } from 'vue'
    
    export default {
      setup () {
        let num1 =  ref(10)  // Number
        let name1 =  ref('Echoyya')  // String
        let arr1 =  ref(['a','d','c','d'])  // Array 
        let obj1 =  ref({age:20})  // Object 
    
        // 获取及改变 ref对象的值,获取内部值的单一属性 value
        console.log(num1.value) // 10
    
        num1.value++
        console.log(num1.value) // 11
        
        return {
          //使用 ref 定义的数据,需要直接 return
          num1,name1,arr1,obj1
        }
      }
    }
    
    
    1. reactive: 用于创建响应式数据,接收一个普通对象然后返回该普通对象的响应式代理,即双向数据绑定,
      • 使用 reactive 定义的数据,不需要逐一 return,可以使用 ES6 的扩展运算符。

      • 解构会破坏双向数据绑定的特性, 变更为单向数据绑定

      • 解决:vue3.0中添加了新特性,可对当前的数据进行转换。将其转换为响应式数据,toRefs将数据包裹即可转换为响应式数据

    import { reactive, toRefs } from 'vue'
    
    export default {
      setup () {
        let data = reactive ({
          num:33,
          arr:['a','d','c','d'],
          obj:{age:20},
        })
         // 获取及改变:reactive 定义的数据,调用时直接 reactive变量名.数据名,
        console.log(data.num) // 33
    
        data.num++
        console.log(data.num) // 34
        
        return {
          ...toRefs(data) 
        }
      }
    }
    

    三、方法的定义和使用

    创建的方法仍然需要 return

    <template>
      <div>
        <p><button @click="clickNum">{{num}}</button></p>
        <p><button @click="clickNum1">{{num1}}</button></p>
        <p><button @click="singleMethod">{{name}}</button></p>
      </div>
    </template>
    
    <script>
    
    import { reactive, ref, toRefs } from 'vue'
    export default {
      setup () {
        let num1 =  ref(10)
        let name =  ref('Echoyya')
        let data = reactive({
          num:33,
        })
    
        // 定义多个方法,不需要逐一 return
        let methods  = {
          clickNum1: () => {
            num1.value++ 
            console.log(num1.value);
          },
          clickNum : () => {
            data.num ++ 
            console.log(data.num);
          }
        }
         // 定义单个方法,需要return
        let singleMethod = () => {
          console.log(name.value)
        }
        return {
          num1,
          name,
          singleMethod,
          ...toRefs(data)
          ...methods,
        }
      }
    }
    
    </script>
    

    四、路由的定义、使用和传参

    1. /src/router/index.js:在路由文件中使用了createRouter方法
    import { createRouter } from 'vue-router'
    const routes = [
      {
        path: '/',
        name: 'Home',
        component: () => import('../views/Home.vue')
      },
      {
        path: '/about',
        name: 'About',
        component: () => import('../views/About.vue')
      }
    ]
    const router = createRouter({
      routes
    })
    
    export default router
    
    
    1. home组件中使用,路由跳转及传递参数
    <template>
      <div>
        <p><button @click="gotoQuery">query跳转</button></p>
        <p><button @click="gotoParams">params跳转</button></p>
      </div>
    </template>
    
    <script>
    
    import { useRouter } from 'vue-router'
    export default {
      setup (){
        // router对象是全局路由的实例。
        let router = useRouter()
    
        // 跳转路由用push: 跳转时可使用name 和 path,传递参数可使用query 和 params
    
        let gotoQuery = () => {
          // query: 可以使用name和path,参数显示在地址栏中, 且页面刷新参数仍在
          router.push({
            // name:'About',
            path:'/about',
            query:{
              name:'Echoyya',
              age: 25,
              obj:JSON.stringify({gender:"f"})
            },
          })
        }
        let gotoParams = () => {
           // params:只能使用name ,不显示在地址栏中,且页面刷新,参数清空 console.log(route.params); 打印空对象
           router.push({
            name:'Home',
            params:{
              name:'Echoyya',
              age: 25,
              obj:JSON.stringify({gender:"f"})
            }
          })
        }
    
        return {
          gotoQuery,
          gotoParams
        }
      }
    }
    
    1. about组件中使用,接收路由参数
    import { useRoute } from 'vue-router'
    export default {
      setup (){
        // route对象表示当前的路由信息,包含了当前 URL 解析得到的信息。包含当前的路径,参数,query对象等。
        let route = useRoute() 
        
        console.log(typeof route.query.age) //string, query传递的参数都是string类型
        console.log(route.query);    //获取query传参
        console.log(route.params);    //获取params传参
        return {}
      }
    }
    

    五、父子组件传值

    1. 父 to 子:通过动态绑定属性的方式,子组件在props 中去接收,

    2. 子 to 父:通过ctx.emit('事件名称', 传递的参数)事件分发的方式, 父组件当中,调用子组件标签上绑定自定义事件,其中包含一个参数,即子组件传递过来的数据

      • ctx.emit('事件名称', 传递的参数)事件分发, ctx是 setup 函数的第二个参数,上下文对象

      • emit 只能接受两个参数,其余不生效,第一个参数:事件名称,第二个: 传递的数据

      • 事件分发,不一定要通过点击事件,也可使用钩子函数等

      • 需要传递多个参数时,emit第二个参数可选择数组或是对象

    father.vue

    <template>
      <div class="wrapper">
        <p>this is father components</p>
        <p> 子组件传递的值:{{childMsg}}</p>
        <!-- msg 自定义属性,send 自定义监听事件-->
        <p><child :msg="msg" @send="getChildData"></child></p>
      </div>
    </template>
    
    <script>
    import { ref } from 'vue'
    import child from '../components/child'
    export default {
      components:{
        child
      },
      setup() {
        let msg = ref('father组件数据')
        let childMsg = ref('')
        let getChildData = (data)=>{
          childMsg.value = data
        }
        return {
          msg,
          childMsg,
          getChildData
        }
      },
    }
    </script>
    

    child.vue

    <template>
      <div>
        this is child components
        <p>父组件传递过来的值:{{msg}}</p>
        <p><button @click="send">传值给父组件</button></p>
      </div>
    </template>
    
    <script>
    import {ref,onMounted, reactive} from  'vue'
    export default {
      name:'child',
      // props 接收的数据,不能直接修改,如props.xxx = yy
      props:{
        msg:{
          type:String , // 数据类型校验
          require:true ,  // 是否必传 默认false
          default:'默认值' // require和default 有些冲突,即必填时,可不设置默认值
        }
      },
      setup(props,ctx){
        console.log(props.msg);   // 父组件传递的数据:father组件数据
    
        let childMsg = ref('child组件数据')
        let data = reactive({
          childNum:10
        })
        
        let send = ()=>{
           ctx.emit('send',childMsg.value)
           // ctx.emit('send',[childMsg.value,data.childNum])  // 数组
           // ctx.emit('send',{  // 对象
           //   msg:childMsg.value,
           //   num:data.childNum
          })  
        }
        return {
         childMsg,
         send,
         ...data
        }
      }
    })
    </script>
    

    六、状态管理的定义和使用

    状态管理即 VUEX,为达到数据共享的目的

    1. /src/store/index.js:在状态管理文件中使用了createStore方法
    import { createStore } from 'vuex'
    
    export default createStore({
      // 定义所需要的状态
      state: {
        name: 'Echoyya',
      },
    
      // 同步修改state ,是方法,不能操作异步操作(包括发送请求及定时器等)
      mutations: {
        // 可接收两个参数:一:state,二:需修改的值,payload(可选)
        setName(state, payload) {
          state.name = payload
        },
      },
      // 提交 mutations
      actions: {
        // 可接收两个参数 一:store, 二 要修改的值
        asyncSetName(store, params) {
          setTimeout(() => {
            // commit 是提交mutation, 提交异步的mutations方法
            store.commit('setName', params)
            console.log(store.state.name) 
          }, 2000)
        }
      },
      // 模块化
      modules: {}
    })
    
    
    1. 组件中调用,VUEX操作数据
    <template>
      <div>
        {{name}}===={{name1}}===={{name2}}
        <p><button @click="setName">设置 name</button></p>
        <p><button @click="asyncSetName">异步设置 name</button></p>
      </div>
    </template>
    
    <script>
    import { reactive, ref, toRefs, computed } from 'vue'
    import { useStore } from 'vuex'
    
    export default {
      setup (){
        //通过 ref 方式
        let name = ref(store.state.name)
       
        // 计算属性 方式
        let name1 = computed(()=>{
          return store.state.name + 'computed'
        })
        
        //reactive 方式
        let data = reactive({
           name2:store.state.name + '_reactive'
        })
        
        // 触发 mutations
        let setName = ()=>{
           console.log(store.state.name)  // Echoyya
           store.commit('setName','nhyya') 
           console.log(store.state.name)  // nhyya
        }
        // 触发 action
        let asyncSetName = ()=>{
            store.dispatch('asyncSetName','nhyya1212') 
        }
        return {
          name,
          name1,
          ...toRefs(data),
          setName,
          asyncSetName
        }
      }
    })
    </script>
    

    七、常用的生命周期

    1. setup:不需要引入的生命周期 ,表示组件创建的过程,且没有this

    2. onMounted:比setup 稍微晚一些执行,表示组件挂载的过程,包括数据, dom元素等,是一个函数,需要传入一个回调函数执行,无参数。

      • 常用于:发送请求、数据初始化的操作、接受路由传递的参数
    3. onUnmounted:与 onMounted 相对应,组件卸载或销毁(路由跳转),常用于清除定时器等操作

    较 VUE2.0 另有哪些改变?

    • 3.0去掉了filter, 没有beforeCreate created,用setup取代

    • setup里没有this

    • 3.0兼容IE12以上

    • 可直接监听数组类型的数据变化

    • 监听的目标为对象本身,不需要像Object.defineProperty一样遍历每个属性,有一定的性能提升

    • 直接实现对象属性的新增/删除

    • 重构 Virtual DOM:模板编译时的优化,将一些静态节点编译成常量

    • 另附上vue3.0 文档地址: https://v3.cn.vuejs.org/

    上述内容并非全部 VUE3 内容,只是我通过一段时间的学习,做的自我总结,以便学习和复习,写的不准确之处还望大神们能留言指正

    作者:Echoyya
    著作权归作者和博客园共有,商业转载请联系作者获得授权,非商业转载请注明出处。
  • 相关阅读:
    《WF编程》系列之17 工作流与外部事件:工作流参数 居然有两个多月没有更新WF笔记,这段时间也许真的太忙了,毕业的事情,工作的事情,从今天起继续更新.
    《WF编程》系列之13 XAML激活 2.3.3 XAML激活
    《WF编程》系列之9 编译工作流:使用WFC.EXE
    《WF编程》系列之11 编译工作流:使用MSBUILD
    《WF编程》系列之15 顺序工作流与SequenceActivity 3 顺序工作流
    《WF编程》系列之16 工作流与外部世界:生存周期事件 3.2 工作流与外部世界
    windows2003技巧
    ASP.NET ViewState 初探
    FreeTextBox实现机制
    .NET实用设计模式:工厂模式(Factory)
  • 原文地址:https://www.cnblogs.com/echoyya/p/14394057.html
Copyright © 2011-2022 走看看