小黑子的——vue从入门到入土过程:第六章

VUE2.0——VUE3.0系列第六章

1. vue 项目git注意

1.首先需要在index.html将 语句dist前面的“/”去掉,否则在打包时会出现无法找到我们所编写的vue文件。
2.删除webpack.config.js文件中

output: {
path: path.resolve(__dirname,./dist’),
publicPath:/dist/,
filename: ‘build.js’
},
publicPath:"/dist"

中 dist前面的 /
3.接着我们在当前项目文件夹中打开命令行窗口,输入 npm run build 命令,enter,等待带包完成,当打包完成时,我们发现项目文件夹中会多出一个.dist文件夹。
4.打包成功后可以通过访问index.html即可直接查看我们的项目效果。

2. 开发流程&云服务器

开发流程思维导图
在这里插入图片描述

3. nginx上线

准备:
使用npm run build将Vue项目打包,得到一个dist文件夹,并上传到服务器。在服务器上安装nginx
apt-get install nginx
配置/etc/nginx/nginx.conf文件

配置:
在http{}里添加server,server是虚拟主机配置,一个站点就是一个server

   server {
        listen 80 ssl;     #端口
        server_name ele.geminglu.cn;     #域名或IP地址
            location / {
                    root   /home/ubuntu/elebackstage/dist;     #3.dist文件的位置
                    try_files $uri $uri/ /index.html;     #4.重定向,如果路由用的是history 没事就需要配置
            }
            location /api {  #当请求跨域时配置端口转发
                    proxy_pass      https://geminglu.cn:3003; #5.转发地址
            }
    }

如果使用HTTPS就需要参考一下配置:

    server {
        listen 443 ssl;     #端口
        server_name ele.geminglu.cn;     #域名
        #证书路径
        ssl_certificate      /home/ubuntu/SSL/Nginx/1_www.geminglu.cn_bundle.crt;   
        ssl_certificate_key  /home/ubuntu/SSL/Nginx/2_www.geminglu.cn.key;
        ssl_session_timeout 5m;
        #请按照以下协议配置
        ssl_protocols TLSv1 TLSv1.1 TLSv1.2; 
        #请按照以下套件配置,配置加密套件,写法遵循 openssl 标准。
        ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE; 
        ssl_prefer_server_ciphers on;
            location / {
                    root   /home/ubuntu/elebackstage/dist;     #dist文件的位置
                    try_files $uri $uri/ /index.html;     #重定向,如果路由用的是history 没事就需要配置
            }
            location /api {  #当请求跨域时配置端口转发
                    proxy_pass      https://geminglu.cn:3003; #转发地址
            }
    }
    server {
        listen 80;
        #填写服务器IP
        server_name 111.229.110.113; 
        #把http的域名请求转成https
        return 301 https://$host$request_uri; 
    }

启动:
在开启服务之前,可以使用 nginx -t 测试一下配置文件的语法是否正确
nginx 开启服务
nginx -s stop 停止服务

4. vue3-项目创建

在这里插入图片描述

5. vue3-项目改造

</router-link>
<router-link to="/cinemas" custom v-slot="{ navigate, isActive }">
<li @click="navigate" :class="isActive ? 'kerwinactive':''">
<i class="iconfont icon-all"></i>
}
<span>影院</span>
</li>
</router-link>
<script>
export·default {
mounted(){
console.log(this.$route.params.id)
}
}
</script>
export default {
mounted(){
this.$store.commit("hide")
console.log(this.$route.params.id)

},
destroyed(){
this.$store.commit("show")

export default createstore({
state:{
isTabbarShow:true
},
mutations:{
hide(state){
state.isTabbarShow = false
}show(state)
state.isTabbarShow = true
}
}
})

6. vue3-reactive

react :
1.类写法
2.函数写法-(不支持状态,,生命周期,支持属性)

reactive的用法与ref的用法相似,也是将数据变成响应式数据,当数据发生变化时UI也会自动更新。不同的是ref用于基本数据类型,而reactive是用于复杂数据类型,比如对象和数组
例如:定义一个对象类型的变量user

<template>
  <div>
    <p>{{ user }}</p>
    <button @click="increase">click me! one year later</button>
  </div>
</template>

<script>
import { reactive } from "vue";
export default {
  name: "reactive",
  setup() {
    const user = reactive({ name: "Alice", age: 12 });
    function increase() {
      ++user.age
    }
    return { user, increase };
  },
};
</script>

如上,当点击按钮时,让数据user.age加1,当Vue发现数据发生变化,UI会自动更新
那我们验证了,确实reactive函数可以将一个复杂数据类型变成响应式数据。

7. vue3-ref

接受一个参数值并返回一个响应式且可改变的 ref 对象。ref 对象拥有一个指向内部值的单一属性 .value。

const count = ref(0)
console.log(count.value) // 0

count.value++
console.log(count.value) // 1

ref 跟 reactive 都是响应系统的核心方法,作为整个系统的入口

可以将 ref 看成 reactive 的一个变形版本,这是由于 reactive 内部采用 Proxy 来实现,而 Proxy 只接受对象作为入参,这才有了 ref 来解决值类型的数据响应,如果传入 ref 的是一个对象,内部也会调用 reactive 方法进行深层响应转换

Ref 是如何创建的
我们还是先从定义抓起,ref 接收一个可选的 unknown 做为入参,接着直接调用 createRef

createRef 先判断 value 是否已经是一个 ref, 如果是则直接返回,如果不是接着判断是不是浅观察,如果是浅观察直接构造一个 ref 返回,不是则将 rawValue 转换成 reactive 再构造一个 ref 返回

export function ref(value?: unknown) {
  return createRef(value)
}

/**
 * @description: 
 * @param {rawValue} 原始值 
 * @param {shallow} 是否是浅观察 
 */
function createRef(rawValue: unknown, shallow = false) {
  // 如果已经是ref直接返回
  if (isRef(rawValue)) {
    return rawValue
  }

  // 如果是浅观察直接观察,不是则将 rawValue 转换成 reactive ,
  // reactive 的定义在下方 
  let value = shallow ? rawValue : convert(rawValue)

  // ref 的结构
  const r = {
    // ref 标识
    __v_isRef: true,
    get value() {
      // 依赖收集
      track(r, TrackOpTypes.GET, 'value')
      return value
    },
    set value(newVal) {
      if (hasChanged(toRaw(newVal), rawValue)) {
        rawValue = newVal
        value = shallow ? newVal : convert(newVal)
        // 触发依赖
        trigger(
          r,
          TriggerOpTypes.SET,
          'value',
          __DEV__ ? { newValue: newVal } : void 0
        )
      }
    }
  }
  return r
}

// 如是是对象则调用 reactive, 否则直接返回 
const convert = <T extends unknown>(val: T): T =>
  isObject(val) ? reactive(val) : val

8. vue3-toRefs

作用:创建一个 ref 对象,其 value 值指向另一个对象中的某个属性。
语法:const name = toRef(person, ’ name ')
应用:要将响应式对象中的某个属性单独提供给外部使用时
扩展:toRefs 与 toRef 功能一致,但可以批量创建多个 ref 对象
语法:toRefs(person)

toRef / toRefs 区别
作用:
toRef 和 toRefs 可以用来复制 reactive 里面的属性然后转成 ref,而且它既保留了响应式,也保留了引用,也就是你从 reactive 复制过来的属性进行修改后,除了视图会更新,原有 ractive 里面对应的值也会跟着更新,如果你知道 浅拷贝 的话那么这个引用就很好理解了,它复制的其实就是引用 + 响应式 ref不加 s 和 加 s 的区别就是这样:

toRef: 复制 reactive 里的单个属性并转成
ref toRefs: 复制 reactive 里的所有属性并转成 ref

9. vue3-props&emit

9.1 Props 声明

props 需要使用 props 选项来定义:

export default {
  props: ['foo'],
  created() {
    // props 会暴露到 `this` 上
    console.log(this.foo)
  }
}

除了使用字符串数组来声明 prop 外,还可以使用对象的形式:

export default {
  props: {
    title: String,
    likes: Number
  }
}

对于以对象形式声明中的每个属性,key 是 prop 的名称,而值则是该 prop 预期类型的构造函数。比如,如果要求一个 prop 的值是 number 类型,则可使用 Number 构造函数作为其声明的值。

对象形式的 props 声明不仅可以一定程度上作为组件的文档,而且如果其他开发者在使用你的组件时传递了错误的类型,也会在浏览器控制台中抛出警告。我们将在本章节稍后进一步讨论有关 prop 校验的更多细节。

9.2 emit

回顾vue2中的emit
在vue2中,子组件想要将自定义事件向上级透传的方式就是this.$emit(<changName>, payload)

child.vue

<template>
<div>
  <button @click="onEmit"> 子组件透传事件 </button>
</div>
</template>
<script>
export default {
  methods: {
    onEmit() {
      this.$emit("on-change", "hi~");
    }
  }
}
</script>

parent.vue

<template>
<div>
  < child @on-change="onChildChange" />
</div>
</template>
<script>
import Child from "./Child.vue";
export default {
  components: {
    Child
  },
  methods: {
    onChildChange(v) {
      console.log(v); // hi~
    }
  }
}
</script>

以上就是vue2 中常见的emit使用方式。关键点就是子组件依赖this.$emit透传,父组件使用子组件并v-on指定子组件透传事件Name.

vue3的emit($emit, emits-options)

在setup()的this 是不指向当前实例的(this为undefined),如果想使用使用$emit的功能,需要借助setup(props, context)中的context;

context会暴露三个组件的property;

export default {
  setup(props, context) {
    // Attribute (非响应式对象)
    console.log(context.attrs)

    // 插槽 (非响应式对象)
    console.log(context.slots)

    // 触发事件 (方法)
    console.log(context.emit)
  }
}

在这里我们需要使用context.emit;如下

child.vue

<template>
  <div>
    <button @click="clickBtn" class="btn-item">hi~</button>
  </div>
</template>
<script>
import { defineComponent } from 'vue'
export default defineComponent({
  setup (props, ctx) {
    const clickBtn = () => {
      ctx.emit("on-change", "hi~");
    };
    return { clickBtn}
  }
})
</script>

parent.vue

<template>
  <div>
    <emit-child @on-change="emitFn" />
  </div>
</template>

<script>
import { defineComponent } from 'vue'
import EmitChild from "./Child.vue"
export default defineComponent({
  components: {
    EmitChild
  },
  setup () {
    const emitFn = v => {
      console.log(v);
    }
    return { emitFn }
  }
})
</script>

10. vue3-生命周期

在这里插入图片描述

<template>
    <div>
        detail
    </div>
</template>

<script>
export default {
    mounted(){
        this.$store.commit("hide")
        console.log(this.$route.params.id)

    },
    beforeUnmount(){
        console.log("beforeUnmount")
    },
    unmounted(){
        this.$store.commit("show")
    }
}
</script>

11. vue3-计算属性

1.基本使用:只读

<template>
  <div>
    <div>计算属性</div>
    <hr>
    <button @click='age=25'>点击</button>
    <div>今年:{{age}}岁了</div>
    <div>明年:{{nextAge}}岁了</div>
  </div>
</template>

<script>
import { ref, computed } from 'vue'

export default {
  name: 'App',
  setup () {
    // 计算属性:简化模板
    // 应用场景:基于已有的数据,计算一种数据
    const age = ref(18)

    // 计算属性基本使用
    const nextAge = computed(() => {
      // 回调函数必须return,结果就是计算的结果
      // 如果计算属性依赖的数据发生变化,那么会重新计算
      return age.value + 1
    })

    return { age, nextAge }
  }
}
</script>

<style lang="less">
</style>

总结:Vue3中计算属性也是组合API风格

  • 回调函数必须return,结果就是计算的结果
  • 如果计算属性依赖的数据发生变化,那么会重新计算
  • 不要在计算中中进行异步操作

2.高级用法:可读可写

<template>
  <div>
    <div>计算属性</div>
    <hr>
    <button @click='age=25'>点击</button>
    <button @click='nextAge=28'>点击修改</button>
    <div>今年:{{age}}岁了</div>
    <div>明年:{{nextAge}}岁了</div>
  </div>
</template>

<script>
import { ref, computed } from 'vue'

export default {
  name: 'App',
  setup () {
    // 计算属性:简化模板
    // 应用场景:基于已有的数据,计算一种数据
    const age = ref(18)

    // // 计算属性基本使用
    // const nextAge = computed(() => {
    //   // 回调函数必须return,结果就是计算的结果
    //   // 如果计算属性依赖的数据发生变化,那么会重新计算
    //   return age.value + 1
    // })

    // 修改计算属性的值
    const nextAge = computed({
      get () {
        // 如果读取计算属性的值,默认调用get方法
        return age.value + 1
      },
      set (v) {
        // v是计算属性下传递的实参
        // 如果要想修改计算属性的值,默认调用set方法
        age.value = v - 1
      }
    })

    return { age, nextAge }
  }
}
</script>

<style lang="less">
</style>

总结:

  • 计算属性可以直接读取或者修改
  • 如果要实现计算属性的修改操作,那么computed的实参应该是对象
  • 读取数据触发get方法
  • 修改数据触发set方法,set函数的形参就是你赋给他的值

12. vue3-watch

<template>
  <div>
    <input type="text" v-model="obj.mytext" />
    <ul>
      <li v-for="data in obj.datalist" :key="data">
        {{ data }}
      </li>
    </ul>
  </div>
</template>
<script>
import { reactive, watch } from "vue";
export default {
  setup() {
    const obj = reactive({
      mytext: "",
      datalist: ["aaa", "abb", "abc", "bbb", "bcc", "add", "bcd"],
      oldlist: ["aaa", "abb", "abc", "bbb", "bcc", "add", "bcd"],
    });

    watch(
      () => obj.mytext,
      () => {
        obj.datalist = obj.oldlist.filter((item) => item.includes(obj.mytext));
      }
    );

    const handleInput = () => {};
    return {
      obj,
      handleInput,
    };
  },
  watch:{
      mytext(){
          
      }
  }
};
</script>

14. vue3-自定义hooks

什么是hooks?
————本质是一个函数,把setup函数中使用的CompositionAPI进行了封装

类似于vue2.x中的mixin

自定义hooks的优势:复用代码,让setup中逻辑更清楚易懂

定义一下Vue3的自定义Hook:

以函数形式抽离一些可复用的方法像钩子一样挂着,随时可以引入和调用,实现高内聚低耦合的目标;

  1. 将可复用功能抽离为外部JS文件
  2. 函数名/文件名以use开头,形如:useXX
  3. 引用时将响应式变量或者方法显式解构暴露出来如:const {nameRef,Fn} = useXX()
    (在setup函数解构出自定义hooks的变量和方法)

实例:

import { ref, watch } from 'vue';
const useAdd= ({ num1, num2 })  =>{
    const addNum = ref(0)
    watch([num1, num2], ([num1, num2]) => {
        addFn(num1, num2)
    })
    const addFn = (num1, num2) => {
        addNum.value = num1 + num2
    }
    return {
        addNum,
        addFn
    }
}
export default useAdd
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值