【问题标题】:Property "" was accessed during render but is not defined on instance在渲染期间访问了属性“”,但未在实例上定义
【发布时间】:2021-11-14 20:44:56
【问题描述】:

我目前正在尝试修复这 4 个主要错误(在本例中使用 Vue 3:

我不确定我的代码有什么问题,因为它适用于除用户输入之外的所有内容

//############--contact.js--############

//--------------- PAGE TITLE ---------------
// Vue object: Title
const PageTitle = {
    data() {
        return {
            title: 'Contact Us'
        }
    }
}

Vue.createApp(PageTitle).mount('#page-title')

//--------------- NAVIGATION (Cart) ---------------
// Vue object: Title
const CartTitle = {
    data() {
        return {
            cart_title: 'Cart'
        }
    }
}

Vue.createApp(CartTitle).mount('#cart-title')

//--------------- NAVIGATION (Main pages) ---------------
// Vue object: Titles
const MainNav = {
    data() {
        return {
            home: 'Home',
            for_hire: 'For Hire',
            about: 'About',
            contact_us: 'Contact Us',
            search: 'Search'
        }
    }
}

Vue.createApp(MainNav).mount('#nav-titles')

//--------------- FORM TITLES ---------------
// Vue object: Titles
const ContactTitles = {
    data() {
        return {
            main_title: 'Contact Us',
            name: 'Name',
            email_address: 'Email Address',
            select_option: 'What is your enquiry about?',
            checkboxes: 'Please click on each wrestling company you know:'
        }
    }
}

Vue.createApp(ContactTitles).mount('#contact-titles')


//--------------- FORM INPUTS ---------------
// Vue object: Inputs
const UserInputs = {
    data() {
        return {
            inputted_name: '',
            inputted_email: '',
            inputted_message: ''
        }   
    },

    methods: {
        checkInput: function () {
            if (this.inputted_name === '' || this.inputted_email === '' || this.inputted_message === '') 
            {
                alert("Please input in all the fields");
            }
        }
    }
}

Vue.createApp(UserInputs).mount('#contact-form-inputs')

// Vue instance: Select options
Vue.createApp({
    data() {
      return {
        selected: 'None',
        options: [
          { text: 'Booking enquiry', value: 'Booking' },
          { text: 'Website improvement', value: 'Website' },
          { text: 'Item enquiry', value: 'Item' },
          { text: 'Previous experiences', value: 'Experience' },
          { text: 'Career opportunity', value: 'Career' }
        ]
      }
    }
}).mount('#select-list')
/* Stylesheet for SIT120 Project - contact.html */
/*----------------------------------------------------*/

/*/////////////////////////-NO margins-//////////////////////////////*/
/* Expands to width of screen*/
body, html {
    margin: 0;
    padding: 0;
}

body {
    background-color: #AAAAAA;
}

/*/////////////////////////-Header Navigation-//////////////////////////////*/

/* Top navigation (cart) */
.cart_nav ul {
    list-style-type: none;
    margin: auto;
    overflow: hidden;
    background-color: #C6393F; 
}

.cart_nav li {
    float: right;
}

.cart_nav li a {
    font-family: Actor;
    font-size: 18px;
    font-style: normal;
    font-weight:normal;
    padding: 15px 55px 15px 20px;
    color: white;
    display: inline-block;
    text-decoration: none;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    transition: all 0.2s linear;
    -webkit-transition: all 0.2s linear;
    -moz-transition: all 0.2s linear;
    
}

.cart_nav li a:hover 
{
    color:#AAAAAA;
}

/*/////////////////////////-Cart Number-//////////////////////////////*/

/* Cart number (circled) */
.cart_items 
{
    font-family: Righteous;
    font-size: 16px;
    font-weight: bold;
    color: white;
    background-color:#2C2C2C;
    float: right; 
    margin-top: 16px;
    margin-right: 16px;
    margin-left: -33px;
    border-radius: 60%;
    width: 25px;
    height: 22px;
    text-align: center; 
}

/*/////////////////////////-Cart icons-//////////////////////////////*/

/* Top navigation ICONS (cart) */
.cart_icon
{
    display:inline-flex;
    width: 40px;
    height: 40px;
    margin-top: -20px;
    margin-bottom: -15px;
    margin-right: -17px;
    padding-left: 8px;
}

/*/////////////////////////-Main navigation-//////////////////////////////*/

/* Main navigation (pages) */
.page_nav ul
{
    list-style-type: none;
    margin: auto;
    overflow: hidden;
    background-color: #2C2C2C;
}

.page_nav li 
{
    float: left;
}

.page_nav li a {
    font-family: Bai Jamjuree;
    font-size: 22px;
    font-weight: bold;
    padding: 15px;
    line-height: 22px;
    color: #AAAAAA;
    display: inline-block;
    padding: 40px 60px 35px 30px;
    text-decoration: none;
    letter-spacing: 0.07em;
    text-transform: uppercase;
    transition: all 0.2s linear;
    -webkit-transition: all 0.2s linear;
}

.page_nav li a:hover 
{
    color:#FFFFFF;
}

.page_nav li a.active
{
    text-decoration: overline;
    color:#FFFFFF;

}
.page_nav li a:focus
{
    text-decoration: overline;
    color:#FFFFFF;

}

/*/////////////////////////-Navigation icon (Search)-//////////////////////////////*/

/* Main navigation search ICON */
.search_icon
{
    display:inline-block;
    width: 35px;
    height: 37px;
    margin-top: -40px;
    margin-bottom: -15px;
    margin-right: -50px;
    padding-left: 13px;
    padding-right: 45px;
}

/*/////////////////////////-LOGO-//////////////////////////////*/

 /* Main logo (Wrestle Hire logo) */
.site_logo
{
    display: inline;
    float: left;
    width: 180px;
    height: 145px; 
    padding-right: 50px;
    margin-bottom: -20px;
    margin-left: -30px;
    margin-top: -10px;
}


.site_logo:hover
{
    cursor: pointer;
}

/*/////////////////////////-Form-//////////////////////////////*/
.form_container {
   background-color: #2C2C2C;
   margin-left: auto;
   margin-right: auto;
   width: 50em;
   padding: 45px;
   border: #C6393F 6px solid;
   border-radius: 4px;
   box-shadow: 20px 20px 20px grey;
}

.form_inputs 
{
    margin-left: 1.2em;
    margin-right: auto;
    width: 100%;
}

.input_container input {
    padding: 15px;
    border: none;
    width: 42em;
    
}

::placeholder {
    font-family: Abel;
    font-size: 18px;;
}

label {
    font-family: Bai Jamjuree;
    font-size: 18px;
    color: #AAAAAA;
    line-height: 2em;
}

input[type="text"]
{
    font-family: Bai Jamjuree;
    font-size: 18px;
    color: #2d2d2d;
    font-size: 1rem;
    background-color: white;
    border-radius: 4px;
}
<html>
    <head>
        <!--Stylesheets and responsiveness-->
        <link rel="stylesheet" type= "text/css" href="contact.css">
        <meta name="viewport" content="width=device-width, initial-scale=1">

        <!--Link Vue Framework-->
        <script src="https://unpkg.com/vue@next"></script>

        <!-- Set responsiveness to screen size -->
        <meta name="viewport" content="width=device-width, initial-scale=1">    

        <!--Google fonts-->
        <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Actor">
        <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Bai Jamjuree">
        <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Righteous">
        <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Abel">

        <!--Page Icon-->
        <link rel="icon" href="../Assets/page_icon.png">

        <!-- Page title-->
        <title id="page-title">{{title}}</title>
    </head>
    
    <body>
        <!--NAVIGATION-->
        <header>
            <!--Top navigation section (login, account and cart)-->
            <div class = "cart_nav" id = "cart-title">
                <ul>
                    <div class = "cart_items">0</div>
                    <li><a href="#cart">{{cart_title}}<img class = "cart_icon" src="../Assets/cart.png" alt="cart_icon"></a></li>
                </ul>
            </div>

              <!--Main navigation section (main pages)-->
            <div class = "page_nav" id = "nav-titles">
                <ul>
                    <!--All main pages will have .html files, this example has the contact as a separate file (and empty files)-->
                    <a href="../Home/home.html"><img href ="../Home/home.html" class = "site_logo" id = "siteLogo" src="../Assets/website_logo.png"/></a>
                    <li><a href="../Home/home.html">{{home}}</a></li>
                    <li><a href="">{{for_hire}}</a></li>
                    <li><a href="">{{about}}</a></li>
                    <li><a class = "active" href="contact.html">{{contact_us}}</a></li>
                    <li class = "search" style="float:right"><a>{{search}}<img class = "search_icon" src="../Assets/search.png" alt="search_icon"></a></li>
                </ul>
            </div>
        </header>

        <!--CONTACT FORM-->
        <h1>contact us</h1>

        <div class="form_container" id = "contact-titles">
            <div class = "form_inputs" id = "contact-form-inputs">
                    <!--Name input-->
                    <div class="input_container">
                        <label for="nameInput">{{name}}</label> <br>
                        <input id="nameInput" type="text" v-model="inputted_name" placeholder="Enter name">
                    </div>
                    <br>

                    <!--Email input-->
                    <div class="input_container">
                        <label for="emailInput">{{email_address}}</label> <br>
                        <input id="emailInput" type="text" v-model="inputted_email" placeholder="example@gmail.com">
                    </div>
                    <br>

                    <!--Selection list-->
                    <div class="select_container" id = "select-list">
                        <select v-model="selected">
                            <label>{{select_option}}</label> <br>
                            <option v-for="option in options" :value="option.value">{{option.text}}</option>
                        </select>
                    </div>
            </div>
        </div>
    </body>

    <!-- Link JavaScript file -->
    <script src="contact.js"></script>
</html>

不要介意丢失的照片,因为我是在 Visual Studio Code 中使用计算机上的图片文件执行此操作的。我已经尝试了我所知道的所有方法来解决它,但没有运气。

希望有一双敏锐的眼睛能帮助我,谢谢

【问题讨论】:

    标签: html vue.js vuejs3


    【解决方案1】:

    安装到#contact-form-inputs 的应用程序实例在其模板中包含对options 的引用 - 但应用程序中没有定义此类数据。

    我的建议是使用单个根 Vue 实例 - 它会简化您的生活。

    //############--contact.js--############
    
    var app = Vue.createApp({
        template: '#main',
        mounted()
        {
          document.title = 'Contact Us';
        }
    });
    app.component('main-nav', {
      template: '#nav_titles',
          data() {
            return {
                home: 'Home',
                for_hire: 'For Hire',
                about: 'About',
                contact_us: 'Contact Us',
                search: 'Search'
            }
        }
    });
    app.component('cart-title', {
        template: '#cart_title',
        data() {
            return {
                cart_title: 'Cart'
            }
        }
    });
    app.component('form-inputs', {
       template: '#form_inputs',
        data() {
            return {
                main_title: 'Contact Us',
                name: 'Name',
                email_address: 'Email Address',
                checkboxes: 'Please click on each wrestling company you know:',
                inputted_name: '',
                inputted_email: '',
                inputted_message: ''
            }
        },
            methods: {
            checkInput: function () {
                if (this.inputted_name === '' || this.inputted_email === '' || this.inputted_message === '') 
                {
                    alert("Please input in all the fields");
                }
            }
        }
    });
    app.component('selection-list', {
       template: '#selection_list',
        data() {
          return {
            selected: 'None',
            select_option: 'What is your enquiry about?',        
            options: [
              { text: 'Booking enquiry', value: 'Booking' },
              { text: 'Website improvement', value: 'Website' },
              { text: 'Item enquiry', value: 'Item' },
              { text: 'Previous experiences', value: 'Experience' },
              { text: 'Career opportunity', value: 'Career' }
            ]
          }
        },
    });
    app.mount('#app');
    /* Stylesheet for SIT120 Project - contact.html */
    /*----------------------------------------------------*/
    
    /*/////////////////////////-NO margins-//////////////////////////////*/
    /* Expands to width of screen*/
    body, html {
        margin: 0;
        padding: 0;
    }
    
    body {
        background-color: #AAAAAA;
    }
    
    /*/////////////////////////-Header Navigation-//////////////////////////////*/
    
    /* Top navigation (cart) */
    .cart_nav ul {
        list-style-type: none;
        margin: auto;
        overflow: hidden;
        background-color: #C6393F; 
    }
    
    .cart_nav li {
        float: right;
    }
    
    .cart_nav li a {
        font-family: Actor;
        font-size: 18px;
        font-style: normal;
        font-weight:normal;
        padding: 15px 55px 15px 20px;
        color: white;
        display: inline-block;
        text-decoration: none;
        letter-spacing: 0.04em;
        text-transform: uppercase;
        transition: all 0.2s linear;
        -webkit-transition: all 0.2s linear;
        -moz-transition: all 0.2s linear;
        
    }
    
    .cart_nav li a:hover 
    {
        color:#AAAAAA;
    }
    
    /*/////////////////////////-Cart Number-//////////////////////////////*/
    
    /* Cart number (circled) */
    .cart_items 
    {
        font-family: Righteous;
        font-size: 16px;
        font-weight: bold;
        color: white;
        background-color:#2C2C2C;
        float: right; 
        margin-top: 16px;
        margin-right: 16px;
        margin-left: -33px;
        border-radius: 60%;
        width: 25px;
        height: 22px;
        text-align: center; 
    }
    
    /*/////////////////////////-Cart icons-//////////////////////////////*/
    
    /* Top navigation ICONS (cart) */
    .cart_icon
    {
        display:inline-flex;
        width: 40px;
        height: 40px;
        margin-top: -20px;
        margin-bottom: -15px;
        margin-right: -17px;
        padding-left: 8px;
    }
    
    /*/////////////////////////-Main navigation-//////////////////////////////*/
    
    /* Main navigation (pages) */
    .page_nav ul
    {
        list-style-type: none;
        margin: auto;
        overflow: hidden;
        background-color: #2C2C2C;
    }
    
    .page_nav li 
    {
        float: left;
    }
    
    .page_nav li a {
        font-family: Bai Jamjuree;
        font-size: 22px;
        font-weight: bold;
        padding: 15px;
        line-height: 22px;
        color: #AAAAAA;
        display: inline-block;
        padding: 40px 60px 35px 30px;
        text-decoration: none;
        letter-spacing: 0.07em;
        text-transform: uppercase;
        transition: all 0.2s linear;
        -webkit-transition: all 0.2s linear;
    }
    
    .page_nav li a:hover 
    {
        color:#FFFFFF;
    }
    
    .page_nav li a.active
    {
        text-decoration: overline;
        color:#FFFFFF;
    
    }
    .page_nav li a:focus
    {
        text-decoration: overline;
        color:#FFFFFF;
    
    }
    
    /*/////////////////////////-Navigation icon (Search)-//////////////////////////////*/
    
    /* Main navigation search ICON */
    .search_icon
    {
        display:inline-block;
        width: 35px;
        height: 37px;
        margin-top: -40px;
        margin-bottom: -15px;
        margin-right: -50px;
        padding-left: 13px;
        padding-right: 45px;
    }
    
    /*/////////////////////////-LOGO-//////////////////////////////*/
    
     /* Main logo (Wrestle Hire logo) */
    .site_logo
    {
        display: inline;
        float: left;
        width: 180px;
        height: 145px; 
        padding-right: 50px;
        margin-bottom: -20px;
        margin-left: -30px;
        margin-top: -10px;
    }
    
    
    .site_logo:hover
    {
        cursor: pointer;
    }
    
    /*/////////////////////////-Form-//////////////////////////////*/
    .form_container {
       background-color: #2C2C2C;
       margin-left: auto;
       margin-right: auto;
       width: 50em;
       padding: 45px;
       border: #C6393F 6px solid;
       border-radius: 4px;
       box-shadow: 20px 20px 20px grey;
    }
    
    .form_inputs 
    {
        margin-left: 1.2em;
        margin-right: auto;
        width: 100%;
    }
    
    .input_container input {
        padding: 15px;
        border: none;
        width: 42em;
        
    }
    
    ::placeholder {
        font-family: Abel;
        font-size: 18px;;
    }
    
    label {
        font-family: Bai Jamjuree;
        font-size: 18px;
        color: #AAAAAA;
        line-height: 2em;
    }
    
    input[type="text"]
    {
        font-family: Bai Jamjuree;
        font-size: 18px;
        color: #2d2d2d;
        font-size: 1rem;
        background-color: white;
        border-radius: 4px;
    }
    <html>
        <head>
            <!--Stylesheets and responsiveness-->
            <link rel="stylesheet" type= "text/css" href="contact.css">
            <meta name="viewport" content="width=device-width, initial-scale=1">
    
            <!--Link Vue Framework-->
            <script src="https://unpkg.com/vue@next"></script>
    
            <!-- Set responsiveness to screen size -->
            <meta name="viewport" content="width=device-width, initial-scale=1">    
    
            <!--Google fonts-->
            <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Actor">
            <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Bai Jamjuree">
            <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Righteous">
            <link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Abel">
    
            <!--Page Icon-->
            <link rel="icon" href="../Assets/page_icon.png">
        </head>
        
        <body>
          <div id="app"></div>
          <template id="nav_titles">
                        <!--Main navigation section (main pages)-->
                <div class = "page_nav">
                    <ul>
                        <!--All main pages will have .html files, this example has the contact as a separate file (and empty files)-->
                        <a href="../Home/home.html"><img href ="../Home/home.html" class = "site_logo" id = "siteLogo" src="../Assets/website_logo.png"/></a>
                        <li><a href="../Home/home.html">{{home}}</a></li>
                        <li><a href="">{{for_hire}}</a></li>
                        <li><a href="">{{about}}</a></li>
                        <li><a class = "active" href="contact.html">{{contact_us}}</a></li>
                        <li class = "search" style="float:right"><a>{{search}}<img class = "search_icon" src="../Assets/search.png" alt="search_icon"></a></li>
                    </ul>
                </div>
          </template>
          <template id="cart_title">
                      <!--Top navigation section (login, account and cart)-->
                <div class = "cart_nav">
                    <ul>
                        <div class = "cart_items">0</div>
                        <li><a href="#cart">{{cart_title}}<img class = "cart_icon" src="../Assets/cart.png" alt="cart_icon"></a></li>
                    </ul>
                </div>
          </template>
          <template id="form_inputs">
                  <div class="form_container">
                <div class = "form_inputs">
                        <!--Name input-->
                        <div class="input_container">
                            <label for="nameInput">{{name}}</label> <br>
                            <input id="nameInput" type="text" v-model="inputted_name" placeholder="Enter name">
                        </div>
                        <br>
    
                        <!--Email input-->
                        <div class="input_container">
                            <label for="emailInput">{{email_address}}</label> <br>
                            <input id="emailInput" type="text" v-model="inputted_email" placeholder="example@gmail.com">
                        </div>
                        <br>
    
                        <!--Selection list-->
                        <selection-list></selection-list>
                </div>
            </div>
          </template>
          <template id="selection_list">
                              <div class="select_container">
                            <select v-model="selected">
                                <label>{{select_option}}</label> <br>
                                <option v-for="option in options" :value="option.value">{{option.text}}</option>
                            </select>
                        </div>
          </template>
        <template id="main">
            <!--NAVIGATION-->
            <header>
                <cart-title></cart-title>
                <main-nav></main-nav>
            </header>
    
            <!--CONTACT FORM-->
            <h1>contact us</h1>
            <form-inputs></form-inputs>
        </template>
        </body>
    
    </html>

    【讨论】:

    • 你介意给我看看这是什么样子吗?我对 Vue 完全陌生,研究过单根 Vue 实例,但仍然不太了解它
    • 而不是多次调用Vue.createApp(),每次都挂载到不同的HTML元素(甚至可能嵌套在另一个已经挂载的Vue实例中)——你只调用一次,将它挂载到最外层的HTML模板中的元素。或者,如果您想利用组件化 - 那么首先创建内部“组件”(并注册它们以供以后在其他模板中使用),然后在其他模板中引用这些组件。
    • 所以,如果 selection list 应该是一个 Vue 组件 - 从 form inputs 组件的模板中删除它的模板,而是通过它的标签名来引用它(例如 &lt;selection-list&gt;)我知道 Vue 指南建议初学者从基于浏览器的运行时开始——但在我看来,如果你切换到 Webpack 和 Single-File-Components 会更容易。
    • 在代码中会是什么样子?你介意给我看看吗?
    • 我已经用代码 sn-p 更新了答案。
    猜你喜欢
    • 2022-01-12
    • 2021-04-26
    • 1970-01-01
    • 1970-01-01
    • 2021-11-16
    • 1970-01-01
    • 2021-11-05
    • 2022-11-22
    • 2021-07-09
    相关资源
    最近更新 更多