404问题、data为什么是函数而不是对象、动态添加属性不能响应式

一、vue项目本地开发完成后部署到服务器后报404是什么原因呢?

1、如何部署?

前后端分离开发模式下,前后端是独立部署的,前端只需要将打包后的构建物上传至目标服务器的web容器指定的静态目录下即可。

Vue项目在构建完后,会生成一系列的静态文件,常规部署只需要将打包后的文件上传至目标服务器即可。如nginx:配置完成后需要重启nginx(nginx -s reload),操作完后就可以在浏览器输入域名进行访问了。

server {
  listen  80;
  server_name  www.xxx.com;
  location / {
    index  /data/dist/index.html;
  }
}

2、404问题

但是vue项目在本地时运行正常,但部署到服务器中,刷新页面,出现404错误是什么原因?

HTTP 404意味着链接指向的资源不存在,只有history模式会出现这个问题,hash模式不会出现。为什么?

根据配置,在地址栏中输入www.xxx.com时会打开我们dist目录下的index.html文件,在跳转路由进入到www.xxx.com/login

www.xxx.com/login页面执行刷新操作,nginx location是没有相关配置的,所以就会出现404.

hash模式下没有问题是因为路由hash模式是用#表示的,如:website.com/#/login,hash的值为#/login。它的特点在于:hash虽然出现在URL中,但不会被包括在HTTP请求中,对服务端完全没有影响,因此改变hash不会重新加载页面。

hash模式下,仅hash符号之前的内容会被包含在请求中,如:website.com/#/login只有website.com会被包含在请求中,因此对于服务端来说,即使没有配置location也不会返回404。

问题的本质是路由是通过js来执行视图切换的,当进入到子路由时刷新页面,web容器没有相对应的页面此时会出现404.只需要配置将任意页面都重定向到index.html,把路由交由前端处理即可。对nginx配置文件.conf修改,添加try_files $uri $uri/ /index.html:

server{
    listen 80;
    server_name www.xxx.com;

    location / {
        index /data/dist/index.html;
        try_files $uri $uri/ /index.html;
    }
}

修改完配置文件后记得配置的更新:

nginx -s reload

设置后服务器就不会再返回404错误页面,因为对于所有路径都会返回index.html文件。为了避免这种情况,你应该在vue应用里面覆盖所有的路由,然后再给出一个404页面

const router=new VueRouter({
    mode:'history',
    routes:[
        {path:'*',component:NotFoundComponent}
    ]
})

关于后端配置方案还有:Apache、nodejs等,思想是一致的。

二、data属性为什么是一个函数而不是一个对象?

组件实例对象data必须为函数,目的是为了防止多个组件实例对象之间共用一个data,产生数据污染。采用函数的形式,initData时会将其作为工厂函数返回全新的data对象。

如果不同组件的data是一个对象,那么修改data中的key会同步修改另一个组件。这是因为它们共用了同一个内存地址,componentA修改的内容同样会对componentB产生影响。

如果采用函数形式定义data,则不会出现这种情况(因为函数返回的对象内存地址并不相同)。修改componentA组件data属性的值,componentB的值不受影响。

vue组件可能会有多个实例,采用函数返回data,使每个实例对象的数据不会受到其他实例对象的污染。

vue源码中会对data类型进行判断,如果不是function则会警告提示。

扩展:在定义Vue实例(即根实例对象)时,data既可以是一个函数也可以是一个对象。因为根实例是单例,不会产生数据污染情况。

三、vue2动态给data添加一个新的属性,视图却没有更新是为什么?

原因:Vue2通过Object.defineProperty实现数据响应式,当访问或修改已经定义过的属性值的时候都能够触发setter和getter。但是为obj添加新属性的时候,却无法触发事件属性的拦截。原因是一开始旧的属性就被设置成了响应式数据,而新增的属性并没有通过Object.defineProperty设置成响应式数据。

解决方案:

(1)Vue.set(要修改的对象,新属性名,新属性值),适用于为对象添加少量属性。

(2)Object.assign({},新对象名, 新对象值即旧对象+新属性)//需要重新定义一个变量,适用于为对象添加多个属性。

(3)this.$forceUpdate()不推荐!!!:$forceUpdate会迫使Vue实例重新渲染。如果需要在vue中做一次强制更新,99.9%的情况是在某个地方做错了事。$forceUpdate仅仅会影响实例本身和插入插槽内容的子组件,而不是所有子组件。

PS:vue3是用过proxy实现数据响应式的,直接动态添加新属性仍可以实现数据响应式。

<template>
    <p v-for="(value,key) in items" :key="key">{{value}}</p>
    <p v-for="(value,key) in newItems" :key="key">{{value}}</p>
    <el-button @click="addNewProperty">动态添加新属性</el-button>
</template>
<script>
import Vue from 'vue'
data{
    return{
        items:{oldProperty:'旧属性'},
        newItems:null
    }
}
methods:{
    addNewProperty(){
        //未更新
        this.items.newProperty='新属性'
        console.log(this.items)
        //方式一:Vue.set()实现更新,需要引入Vue
        Vue.set(this.items,'newProperty','新属性')
        //方式二:Object.assign()实现更新
        this.newItems=Object.assign({},this.newItems,{...this.items,newProperty:'新属性'})
        //方式三:$forceUpdate()
        this.$forceUpdate()
    }
}
</script>

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值